写在前面
portal提供了一种将子节点渲染到存在于父组件以外的DOM节点的优秀方案
官方介绍
//portal提供了一种将子节点渲染到存在于父组件以外的DOM节点的优秀方案
ReactDOM.createPortal(child, container)
//第一个参数(child)是任何可渲染的React子元素(字符串或fragment)
//第二个参数container是一个DOM元素
为什么需要Portals
当你想把父组件的某个子组件渲染到页面中其它盒子(非父组件子树)里的时候,就用 portal
场景
写modal的时候
一般思路
可能很多同学会直接在JSX中把Modal画出来,像这样
<div class="modal">
<div> ... </div>
{ needModal ? <Modal /> : null }
</div>
缺陷
- modal生成的代码会与JSX中的代码冗余在一起,而modal的显示位置大多情况是在中间位置,目前modal与其他组件冗余,我们需要CSS的position属性控制modal位置,就要求从modal往上一直到body没有其他postion是relative的元素干扰
- modal的样式会和其他组件的样式嵌套在一起,容易引起冲突
不好的思路
有的同学可能会想到,我们可以在最外层body标签出专门定义一个modal的位置,然后通过redux进行发射信号进行控制,其实效果就像下图。
\
方案
我们既希望在组件的JSX中选择使用modal,把modal用得像一个普通组件一样,但是又希望modal内容显示在另一个地方,就需要Portal上场了。
Portal就是建立一个“传送门”,让modal这样的组件在表示层和其他组件没有任何差异,但是渲染的东西却像经过传送门一样出现在另一个地方。
如何使用Portals
- 引入createPortal 在react-dom中
import { createPortal } from 'react-dom'
- 在constructor定义参数container 就是this.node,利用window.document 记录doc参数 = > 定义this.node 创建div节点=>利用constructor当前的body下挂载在一个div节点上
constructor(props){
super(props);
const doc = window.document; //记录参数 利用window.document
this.node = doc.createElement("div");// 定义this.node 创建一个div节点
doc.body.appendChild(this.node); // 当前的body下挂载一个div节点
}
- 利用createPortal( )方法传递两个参数
render() {
return createPortal(
<div className='dialog'>
<h3>Modal</h3>
</div>,
this.node)
}
- 在componetWillUnmout取消绑定,不然会造成重复渲染。
//在willUnmount中实现订阅和取消订阅
componentWillUnmount() { window.document.body.removeChild(this.node) //记录参数 利用window.document
}
写在后面
- 欢迎关注公众号“燕小书”,回复:“技术交流”进微信技术交流群,公众号会陆续发布优质文章。
- 前端知识库: www.yuque.com/linhao-00ft…