前言
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。它解决了实现组件时候的一个痛点,比如当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框:
ReactDOM.createPortal(child, container)
1. SPA App 一般只有一个根结点,假如有一个api可以比较好的将一个组件mount在root以外,就不会受父级组件样式的影响
2.用createPortal实现一个Portal
- class版
class Portal extends React.PureComponent{
componentDidMount() { //首先去body下创建一个id=modal-root的标签
this.rootEle = document.createElement('div');
this.rootEle.setAttribute('id','modal-root');
document.body.appendChild(this.rootEle);
this.forceUpdate();
}
render(){ //这里只是简单的让modal组件显示和隐藏
if(!this.rootEle) return null;
return ReactDOM.createPortal(<div>
{this.props.children}
</div>, this.rootEle);
}
}
- hook版
3.实现useModal
function useModal(){
const [isShow, setIsShow] = useState(false);
const show = useCallback(() => setIsShow(true), []);
const hide = useCallback(() => setIsShow(false), []);
const Modal = ({children}) => (isShow && <Portal>{children}</Portal>);
return {
show,
hide,
Modal,
};
}
3.调用useModal
export default memo(function App(){
const {show, hide, Modal} = useModal();
return <>
<button onClick={show}>modal显示</button>
<Modal>
<input type="text" />
<button onClick={hide}>关闭</button>
</Modal>
</>
});
4.当点击 modal显示 button,请看浏览器里的element,是不是多了一个id="modal-root"的div
同时渲染结果如下: