通常情况下我们使用React封装的弹窗组件是直接挂载某个div节点上,有时候弹窗不能直接覆盖整个屏幕,不能满足我们的需求,在antd等ui组件中实现的Dialog是直接挂载在body节点下的,那是怎么实现的呢?
让我们来了解一下react中传送门的概念吧?
- react v16之后,react就为开发者们提供了Protals,
用于实现内容传送的功能
,这是一个createDom对象下的方法明接收两个参数; ReactDOM.createProtal(children, container);
- Children: 任何可渲染的React元素;
- Container: 需要被挂载的DOM元素;
- Dialog对话框组件设计思路
- 创建Dialog组件实例时将组件挂载到body下,卸载组件时从body上移除组件实例
- 具体实现
- 使用Dialog组件
import React, { useState } from 'react';
import Dialog from '../../components/Dialog/index';
import { Button } from 'antd';
import './index.less';
const UseDialog = () => {
const [isShowDialog, setIsShowDialog] = useState(false);
const toggleDialog = () => {
setIsShowDialog(prev => !prev.isShowDialog);
}
const closeDialog = () => {
setIsShowDialog(false);
}
const onSure = () => {
console.log('确定...');
setTimeout(() => {
setIsShowDialog(false);
}, 2000);
}
return (
<div className="p-use-dialog">
<Button onClick={toggleDialog}>使用弹窗类组件</Button>
{
isShowDialog
&& <Dialog
dialogWidth='80%'
onCancle={closeDialog}
onOk={onSure}
cancelText="残忍离开"
sureText="我再想想"
>
<div className='dialog-content'>具体内容请写在这里...</div>
</Dialog>}
</div>
);
}
export default UseDialog;
- Dialog 实现
import React, { useEffect } from 'react';
import { createPortal } from 'react-dom';
import './index.less';
import { Divider, Button } from 'antd';
const Dialog = (props) => {
const node = document.createElement('div');
document.body.appendChild(node);
useEffect(() => {
return () => {
document.body.removeChild(node);
};
}, []);
return createPortal(
<div className="com-dialog">
<div className="com-dialog-inner" style={{width: props.dialogWidth}}>
<div className="dialog-title">{props.title}</div>
<Divider />
<div className="content">{props.children}</div>
<Divider />
<div className="btn">
<Button type="default" onClick={props.onCancle}>{props.cancelText || '取消'}</Button>
<Button type="primary" onClick={props.onOk}>{props.sureText || '确定'}</Button>
</div>
</div>
</div>,
node
)
}
export default Dialog;
- 最终效果预览
拓展
protal不仅可以实现一些弹窗,对话框组件,在使用到地图Api,图表的业务场景下也是很实用的,一般而言,地图的层级一般是比较高的,对于地图封装的一些方法例如滚动,禁止滚动等场景下,地图的滚动事件和浏览的的滚动事件可能会发生冲突,此时可以通过将地图挂载其他的节点中,已避免事件冲突。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!