日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
實現(xiàn)一個帶有動效的React彈窗組件

我們在寫一些 UI 組件時,若不考慮動效,就很容易實現(xiàn),主要就是有無的切換(類似于 Vue 中的 v-if 屬性)或者可見性的切換(類似于 Vue 中的 v-show 屬性)。

成都創(chuàng)新互聯(lián)公司主營崇州網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app軟件定制開發(fā),崇州h5小程序開發(fā)搭建,崇州網(wǎng)站營銷推廣歡迎崇州等地區(qū)企業(yè)咨詢

1. 沒有動效的彈窗

在 React 中,可以這樣來實現(xiàn):

 
 
 
 
  1. interface ModalProps {
  2.   open: boolean;
  3.   onClose?: () => void;
  4.   children?: any;
  5. }
  6. const Modal = ({open. onClose, children}: ModalProps) => {
  7.   if (!open) {
  8.     return null;
  9.   }
  10.   return createPortal(
  11.     {children}
  •     x
  •   
  • , document.body);
  • };
  • 使用方式:

     
     
     
     
    1. const App = () => {
    2.   const [open, setOpen] = useState(false);
    3.   return (
    4.     
    5.        setOpen(true)}>show modal
    6.        setOpen(false)}>
    7.         modal content
    8.       
    9.     
  •   );
  • };
  • 我們在這里就是使用 open 屬性來控制展示還是不展示,但完全沒有漸變的效果。

    若我們想實現(xiàn) fade, zoom 等動畫效果,還需要對此進行改造。

    2. 自己動手實現(xiàn)有動效的彈窗

    很多同學(xué)在自己實現(xiàn)動效時,經(jīng)常是展示的時候有動效,關(guān)閉的時候沒有動效。都是動效的時機沒有控制好。這里我們先自己來實現(xiàn)一下動效的流轉(zhuǎn)。

    剛開始我實現(xiàn)的時候,動效只有開始狀態(tài)和結(jié)束狀態(tài),需要很多的變量和邏輯來控制這個動效。

    后來我參考了 react-transition-group 組件的實現(xiàn),他是將動效拆分成了幾個部分,每個部分分別進行控制。

    • 展開動效的順序:enter -> enter-active -> enter-done;

    • 關(guān)閉動效的順序:exit -> exit-active -> exit-done;

    動效過程在 enter-active 和 exit-active 的過程中。

    我們再通過一個變量 active 來控制是關(guān)閉動效是否已執(zhí)行關(guān)閉,參數(shù) open 只控制是執(zhí)行展開動效還是關(guān)閉動效。

    當(dāng) open 和 active 都為 false 時,才銷毀彈窗。

     
     
     
     
    1. const Modal = ({ open, children, onClose }) => {
    2.   const [active, setActive] = useState(false); // 彈窗的存在周期
    3.   if (!open && !active) {
    4.     return null;
    5.   }
    6.   return ReactDOM.createPortal(
    7.     
    8.       {children}
  •       
  •         x
  •       
  •     
  • ,
  •     document.body,
  •   );
  • };
  • 這里我們接著添加動效過程的變化:

     
     
     
     
    1. const [aniClassName, setAniClassName] = useState(''); // 動效的class
    2. // transition執(zhí)行完畢的監(jiān)聽函數(shù)
    3. const onTransitionEnd = () => {
    4.   // 當(dāng)open為rue時,則結(jié)束狀態(tài)為'enter-done'
    5.   // 當(dāng)open未false時,則結(jié)束狀態(tài)為'exit-done'
    6.   setAniClassName(open ? 'enter-done' : 'exit-done');
    7.   // 若open為false,則動畫結(jié)束時,彈窗的生命周期結(jié)束
    8.   if (!open) {
    9.     setActive(false);
    10.   }
    11. };
    12. useEffect(() => {
    13.   if (open) {
    14.     setActive(true);
    15.     setAniClassName('enter');
    16.     // setTimeout用來切換class,讓transition動起來
    17.     setTimeout(() => {
    18.       setAniClassName('enter-active');
    19.     });
    20.   } else {
    21.     setAniClassName('exit');
    22.     setTimeout(() => {
    23.       setAniClassName('exit-active');
    24.     });
    25.   }
    26. }, [open]);

    Modal 組件完整的代碼如下:

     
     
     
     
    1. const Modal = ({ open, children, onClose }) => {
    2.   const [active, setActive] = useState(false); // 彈窗的存在周期
    3.   const [aniClassName, setAniClassName] = useState(''); // 動效的class
    4.   const onTransitionEnd = () => {
    5.     setAniClassName(open ? 'enter-done' : 'exit-done');
    6.     if (!open) {
    7.       setActive(false);
    8.     }
    9.   };
    10.   useEffect(() => {
    11.     if (open) {
    12.       setActive(true);
    13.       setAniClassName('enter');
    14.       setTimeout(() => {
    15.         setAniClassName('enter-active');
    16.       });
    17.     } else {
    18.       setAniClassName('exit');
    19.       setTimeout(() => {
    20.         setAniClassName('exit-active');
    21.       });
    22.     }
    23.   }, [open]);
    24.   if (!open && !active) {
    25.     return null;
    26.   }
    27.   return ReactDOM.createPortal(
    28.     
    29.       {children}
  •       
  •         x
  •       
  •     
  • ,
  •     document.body,
  •   );
  • };
  • 動效的流轉(zhuǎn)過程已經(jīng)實現(xiàn)了,樣式也要一起寫上。比如我們要實現(xiàn)漸隱漸現(xiàn)的 fade 效果:

     
     
     
     
    1. .enter {
    2.   opacity: 0;
    3. }
    4. .enter-active {
    5.   transition: opacity 200ms ease-in-out;
    6.   opacity: 1;
    7. }
    8. .enter-done {
    9.   opacity: 1;
    10. }
    11. .exit {
    12.   opacity: 1;
    13. }
    14. .exit-active {
    15.   opacity: 0;
    16.   transition: opacity 200ms ease-in-out;
    17. }
    18. .exit-done {
    19.   opacity: 0;
    20. }

    如果是要實現(xiàn)放大縮小的 zoom 效果,修改這幾個 class 就行。

    一個帶有動效的彈窗就已經(jīng)實現(xiàn)了。

    使用方式:

     
     
     
     
    1. const App = () => {
    2.   const [open, setOpen] = useState(false);
    3.   return (
    4.     
    5.        setOpen(true)}>show modal
    6.        setOpen(false)}>
    7.         modal content
    8.       
    9.     
  •   );
  • };
  • 類似地,還有 Toast 之類的,也可以這樣實現(xiàn)。

    3. react-transition-group

    我們在實現(xiàn)動效的思路上借鑒了 react-transition-group 中的 CSSTransition 組件。 CSSTransition 已經(jīng)幫我封裝好了動效展開和關(guān)閉的過程,我們在實現(xiàn)彈窗時,可以直接使用該組件。

    這里有一個重要的屬性: unmountOnExit ,表示在動效結(jié)束后,卸載該組件。

     
     
     
     
    1. const Modal = ({ open, onClose }) => {
    2.   // http://reactcommunity.org/react-transition-group/css-transition/
    3.   // in屬性為true/false,true為展開動效,false為關(guān)閉動效
    4.   return createPortal(
    5.     
    6.       
    7.         {children}
  •         
  •           x
  •         
  •       
  •     ,
  •     document.body,
  •   );
  • };
  • 在使用 CSSTransition 組件后,Modal 的動效就方便多了。

    4. 總結(jié)

    至此已把待動效的 React Modal 組件實現(xiàn)出來了。雖然 React 中沒有類似 Vue 官方定義的  標(biāo)簽,不過我們可以自己或者借助第三方組件來實現(xiàn)。


    分享題目:實現(xiàn)一個帶有動效的React彈窗組件
    分享路徑:http://www.5511xx.com/article/dhedgho.html

    其他資訊