千家信息网

React中如何实现一个动效弹窗组件

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,本文小编为大家详细介绍"React中如何实现一个动效弹窗组件",内容详细,步骤清晰,细节处理妥当,希望这篇"React中如何实现一个动效弹窗组件"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一
千家信息网最后更新 2025年01月23日React中如何实现一个动效弹窗组件

本文小编为大家详细介绍"React中如何实现一个动效弹窗组件",内容详细,步骤清晰,细节处理妥当,希望这篇"React中如何实现一个动效弹窗组件"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

1. 没有动效的弹窗

在 React 中,可以这样来实现:

interface ModalProps {  open: boolean;  onClose?: () => void;  children?: any;}const Modal = ({open. onClose, children}: ModalProps) => {  if (!open) {    return null;  }  return createPortal(
{children}
x
, document.body);};

使用方式:

const App = () => {  const [open, setOpen] = useState(false);  return (    
setOpen(false)}> modal content
);};

2. 自己动手实现有动效的弹窗

很多同学在自己实现动效时,经常是展示的时候有动效,关闭的时候没有动效。都是动效的时机没有控制好。这里我们先自己来实现一下动效的流转。

刚开始我实现的时候,动效只有开始状态和结束状态,需要很多的变量和逻辑来控制这个动效。

后来我参考了react-transition-group组件的实现,他是将动效拆分成了几个部分,每个部分分别进行控制。

  1. 展开动效的顺序:enter -> enter-active -> enter-done;

  2. 关闭动效的顺序:exit -> exit-active -> exit-done;

动效过程在enter-activeexit-active的过程中。

我们再通过一个变量 active 来控制是关闭动效是否已执行关闭,参数 open 只控制是执行展开动效还是关闭动效。

当 open 和 active 都为 false 时,才销毁弹窗。

const Modal = ({ open, children, onClose }) => {  const [active, setActive] = useState(false); // 弹窗的存在周期  if (!open && !active) {    return null;  }  return ReactDOM.createPortal(    
{children}
x
, document.body, );};

这里我们接着添加动效过程的变化:

const [aniClassName, setAniClassName] = useState(''); // 动效的class// transition执行完毕的监听函数const onTransitionEnd = () => {  // 当open为rue时,则结束状态为'enter-done'  // 当open未false时,则结束状态为'exit-done'  setAniClassName(open ? 'enter-done' : 'exit-done');  // 若open为false,则动画结束时,弹窗的生命周期结束  if (!open) {    setActive(false);  }};useEffect(() => {  if (open) {    setActive(true);    setAniClassName('enter');    // setTimeout用来切换class,让transition动起来    setTimeout(() => {      setAniClassName('enter-active');    });  } else {    setAniClassName('exit');    setTimeout(() => {      setAniClassName('exit-active');    });  }}, [open]);

Modal 组件完整的代码如下:

const Modal = ({ open, children, onClose }) => {  const [active, setActive] = useState(false); // 弹窗的存在周期  const [aniClassName, setAniClassName] = useState(''); // 动效的class  const onTransitionEnd = () => {    setAniClassName(open ? 'enter-done' : 'exit-done');    if (!open) {      setActive(false);    }  };  useEffect(() => {    if (open) {      setActive(true);      setAniClassName('enter');      setTimeout(() => {        setAniClassName('enter-active');      });    } else {      setAniClassName('exit');      setTimeout(() => {        setAniClassName('exit-active');      });    }  }, [open]);  if (!open && !active) {    return null;  }  return ReactDOM.createPortal(    
{children}
x
, document.body, );};

动效的流转过程已经实现了,样式也要一起写上。比如我们要实现渐隐渐现的 fade 效果:

.enter {  opacity: 0;}.enter-active {  transition: opacity 200ms ease-in-out;  opacity: 1;}.enter-done {  opacity: 1;}.exit {  opacity: 1;}.exit-active {  opacity: 0;  transition: opacity 200ms ease-in-out;}.exit-done {  opacity: 0;}

如果是要实现放大缩小的 zoom 效果,修改这几个 class 就行。

一个带有动效的弹窗就已经实现了。

使用方式:

const App = () => {  const [open, setOpen] = useState(false);  return (    
setOpen(false)}> modal content
);};

3. react-transition-group

我们在实现动效的思路上借鉴了 react-transition-group 中的CSSTransition组件。CSSTransition已经帮我封装好了动效展开和关闭的过程,我们在实现弹窗时,可以直接使用该组件。

这里有一个重要的属性:unmountOnExit,表示在动效结束后,卸载该组件。

const Modal = ({ open, onClose }) => {  // http://reactcommunity.org/react-transition-group/css-transition/  // in属性为true/false,true为展开动效,false为关闭动效  return createPortal(          
{children}
x
, document.body, );};

在使用 CSSTransition 组件后,Modal 的动效就方便多了。

读到这里,这篇"React中如何实现一个动效弹窗组件"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

0