计划 1 一般应用
在组件中间接创立 modal 显示:
const {useState, useMemo} = React
const useModal = () => {const [visible, setVisible] = useState(false)
return useMemo(() => {
return {
visible,
show: () => {setVisible(true)
},
close: () => {setVisible(false)
}
}
}, [visible])
}
function App() {const modal = useModal()
return <>
<button onClick={modal.show}> 显示 modal
</button>
<Modal visible={modal.visible} close={modal.close}>qwerty</Modal>
</>
}
ReactDOM.render(<App/>,
document.getElementById('root')
);
这里我应用了 hooks 的计划来创立 modal
modal 组件:
const stopPropagation = ev => ev.stopPropagation()
/**
* 点击 x 和 mask 的时候能够敞开 modal
* @param props
* @return {*|JSX.Element}
* @constructor
*/
function Modal1(props) {return props.visible && <div onClick={props.close} className="modal-container">
<div className="modal-box" onClick={stopPropagation}>
<div className="modal-title">
<span> 模态框 </span>
<span className="modal-close-icon" onClick={props.close}>x</span>
</div>
{props.children}
</div>
</div>
}
增加了整个 div 的 click 事件, 使得其在点击空白区域时能够触发 close 事件
应用这种办法增加 modal, 长处就是应用简略
然而须要在以后组件援用 modal, 不能缓存 modal
计划 2 指令式的调用
代码:
const {useRef} = React
const {body} = document
const show = () => {const Dom = document.createElement('div')
Dom.classList.add('modal-container')
body.appendChild(Dom)
const close = () => {ReactDOM.unmountComponentAtNode(Dom)
body.removeChild(Dom)
}
ReactDOM.render(<Modal close={close}/>, Dom)
}
const showV2 = () => {
let Dom
if (!showV2.cacheDom) {let _Dom = document.createElement('div')
_Dom.classList.add('modal-container')
body.appendChild(_Dom)
showV2.cacheDom = _Dom
Dom = _Dom
} else {
Dom = showV2.cacheDom
Dom.style.display = 'block'
}
const close = () => {Dom.style.display = 'none'}
ReactDOM.render(<Modal close={close}/>, Dom)
}
showV2.cacheDom = null
function App() {
return <>
<button onClick={show}> 显示 modal
</button>
<button onClick={showV2}> 显示 modal (缓存 modal)
</button>
</>
}
ReactDOM.render(<App/>,
document.getElementById('root')
);
灵便应用 react-dom 的 api ReactDOM.render
和 ReactDOM.unmountComponentAtNode
通过 api 给 dom 挂载 (解除) 咱们须要的组件
这样应用有 2 个次要的长处:
- 指令式调用, 不必在 组件里引入 modal 再申明一个状态值和显示 / 暗藏的办法来管制他, 这些冗余的操作(尽管这些货色能够通过一些计划来解决, 然而仍旧很麻烦)
- 能够缓存 modal, 在第二次调用时 只须要扭转 display 即可
在很多组件库里, 这种写法是被常常用到的, 比方 ant-design 里的 message 和 modal(局部)
计划 3 应用 react 的 api 强化计划 1
这里须要说到的是 react 的 api : createPortal
, 官网链接: https://zh-hans.reactjs.org/d…
来自官网的一句简略介绍: Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优良的计划
其实用起来和计划一 是差不多的, 关键在于 modal 的代码不一样:
const {body} = document
function Modal(props) {
return ReactDOM.createPortal(<div className="modal-container" style={{display: props.visible ? 'block' : 'none'}}>
<div className="modal-box">
<div className="modal-title">
<span> 模态框 </span>
<span className="modal-close-icon" onClick={props.close}>x</span>
</div>
{props.children}
</div>
</div>
, body)
}
长处
-
事件冒泡, 在
Modal
里面尝试包裹一层 div, 再增加 click 事件监听:<div onClick={ev => {console.log(ev, ev.target) }}> <Modal visible={modal.visible} close={modal.close}/> </div>
在某些非凡状况下比拟不便, 能够将一些事件 api 裸露进去, 并且也不影响外部
- 当父组件增加
overflow: hidden 或 z-index
时, modal 并不会被暗藏
这个长处当然是绝对于计划一来说的
总结
总结下 react 里根本就这几种根本计划, 如果有脱漏的中央也麻烦留个言告知下
这里放上这篇文章里的所有代码, 如果有帮忙到了你, 麻烦点下 star, 感激不尽
https://github.com/Grewer/JsD…