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

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

新聞中心

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

我們?cè)趯?xiě)一些 UI 組件時(shí),若不考慮動(dòng)效,就很容易實(shí)現(xiàn),主要就是有無(wú)的切換(類(lèi)似于 Vue 中的 v-if 屬性)或者可見(jiàn)性的切換(類(lèi)似于 Vue 中的 v-show 屬性)。

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

1. 沒(méi)有動(dòng)效的彈窗

在 React 中,可以這樣來(lái)實(shí)現(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.     
  •   );
  • };
  • 我們?cè)谶@里就是使用 open 屬性來(lái)控制展示還是不展示,但完全沒(méi)有漸變的效果。

    若我們想實(shí)現(xiàn) fade, zoom 等動(dòng)畫(huà)效果,還需要對(duì)此進(jìn)行改造。

    2. 自己動(dòng)手實(shí)現(xiàn)有動(dòng)效的彈窗

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

    剛開(kāi)始我實(shí)現(xiàn)的時(shí)候,動(dòng)效只有開(kāi)始狀態(tài)和結(jié)束狀態(tài),需要很多的變量和邏輯來(lái)控制這個(gè)動(dòng)效。

    后來(lái)我參考了 react-transition-group 組件的實(shí)現(xiàn),他是將動(dòng)效拆分成了幾個(gè)部分,每個(gè)部分分別進(jìn)行控制。

    • 展開(kāi)動(dòng)效的順序:enter -> enter-active -> enter-done;

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

    動(dòng)效過(guò)程在 enter-active 和 exit-active 的過(guò)程中。

    我們?cè)偻ㄟ^(guò)一個(gè)變量 active 來(lái)控制是關(guān)閉動(dòng)效是否已執(zhí)行關(guān)閉,參數(shù) open 只控制是執(zhí)行展開(kāi)動(dòng)效還是關(guān)閉動(dòng)效。

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

     
     
     
     
    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,
  •   );
  • };
  • 這里我們接著添加動(dòng)效過(guò)程的變化:

     
     
     
     
    1. const [aniClassName, setAniClassName] = useState(''); // 動(dòng)效的class
    2. // transition執(zhí)行完畢的監(jiān)聽(tīng)函數(shù)
    3. const onTransitionEnd = () => {
    4.   // 當(dāng)open為rue時(shí),則結(jié)束狀態(tài)為'enter-done'
    5.   // 當(dāng)open未false時(shí),則結(jié)束狀態(tài)為'exit-done'
    6.   setAniClassName(open ? 'enter-done' : 'exit-done');
    7.   // 若open為false,則動(dòng)畫(huà)結(jié)束時(shí),彈窗的生命周期結(jié)束
    8.   if (!open) {
    9.     setActive(false);
    10.   }
    11. };
    12. useEffect(() => {
    13.   if (open) {
    14.     setActive(true);
    15.     setAniClassName('enter');
    16.     // setTimeout用來(lái)切換class,讓transition動(dòng)起來(lái)
    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(''); // 動(dòng)效的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,
  •   );
  • };
  • 動(dòng)效的流轉(zhuǎn)過(guò)程已經(jīng)實(shí)現(xiàn)了,樣式也要一起寫(xiě)上。比如我們要實(shí)現(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. }

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

    一個(gè)帶有動(dòng)效的彈窗就已經(jīng)實(shí)現(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.     
  •   );
  • };
  • 類(lèi)似地,還有 Toast 之類(lèi)的,也可以這樣實(shí)現(xiàn)。

    3. react-transition-group

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

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

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

    4. 總結(jié)

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


    分享文章:實(shí)現(xiàn)一個(gè)帶有動(dòng)效的React彈窗組件
    本文鏈接:http://m.5511xx.com/article/dhedgho.html

    其他資訊