自己实现动效的React弹窗

回到文章>>

COPYHTML

<div id="app"></div> <div id="modal-container"></div>

COPYCSS

.modal{width:200px;height:200px;background-color:#ccc}.fade-enter{opacity:0}.fade-enter-active{transition:opacity 200ms ease-in-out;opacity:1}.fade-enter-done{opacity:1}.fade-exit{opacity:1}.fade-exit-active{opacity:0;transition:opacity 200ms ease-in-out}.fade-exit-done{opacity:0}.zoom-enter{transform:scale(0.3)}.zoom-enter-active{transition:transform 200ms ease-in-out;transform:scale(1)}.zoom-enter-done{transform:scale(1)}.zoom-exit{transform:scale(1)}.zoom-exit-active{transform:scale(0);transition:transform 200ms ease-in-out}.zoom-exit-done{transform:scale(0)}

COPYJAVASCRIPT

const { useEffect, useState, createPortal } = React; const Modal = ({ open, animaionPrefix, 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( <div className={classNames("modal", `${animaionPrefix}-${aniClassName}`)} onTransitionEnd={onTransitionEnd}> <div className="modal-content">{children}</div> <div className="modal-close-btn" onClick={onClose}> x </div> </div>, document.getElementById("modal-container") ); }; const App = () => { const [fadeModalOpen, setFadeModalOpen] = useState(false); const [zoomModalOpen, setZoomModalOpen] = useState(false); return ( <div className="app"> <button onClick={() => setFadeModalOpen(!fadeModalOpen)}>show fade modal</button> <button onClick={() => setZoomModalOpen(!zoomModalOpen)}>show zoom modal</button> <Modal open={fadeModalOpen} animaionPrefix="fade" onClose={() => setFadeModalOpen(false)}> fade modal content </Modal> <Modal open={zoomModalOpen} animaionPrefix="zoom" onClose={() => setZoomModalOpen(false)}> zoom modal content </Modal> </div> ); }; ReactDOM.render(<App />, document.getElementById("app"));
新窗口打开