有错误欢迎指正!?
Portals 用来将子节点渲染到父组件 DOM 层次结构之外的 DOM 节点。
使用方法:
ReactDOM.createPortal(child, container)
第一个child参数就是自组建,container就是需要挂载到的dom节点
一. 为什么要有portals
- 在React V16之前,子dom节点只能在父dom节点内渲染,所以想重新渲染的话,必须添加一个div,像这样
<div>
{this.props.children}
</div>
- 但是React V16提供了Portals,就不需要必须添加div了,完全可以这么写:
render() {
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}
- 官网的解释为
A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually “break out” of its container. For example, dialogs, hovercards, and tooltips.
实际意思就是当父组件有hidden或者z-index属性,dialogs, hovercards和tooltips 这一类需要在上层的组件很有可能被遮盖。所以才有Portals这个属性,可以让自组件在父组件的上方不被遮盖。
二. Event事件的处理:事件冒泡
注意: 一个从 portal 内部会触发的事件会一直冒泡至包含 React tree 的祖先。
下面这个是官网的例子:app-root和modal-root是兄弟dom节点
<html>
<body>
<div id="app-root"></div>
<div id="modal-root"></div>
</body>
</html>
首先,创建一个Modal组件,调用Modal时的父组件为Parent,Parent的父节点为app-root,但是Model挂载在modal-root下面
但是,Parent 组件能够捕获到未被捕获的从兄弟节点 #modal-root 冒泡上来的事件。
const appRoot = document.getElementById('app-root');
const modalRoot = document.getElementById('modal-root');
class Modal extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount() {
// The portal element is inserted in the DOM tree after
// the Modal's children are mounted, meaning that children
// will be mounted on a detached DOM node. If a child
// component requires to be attached to the DOM tree
// immediately when mounted, for example to measure a
// DOM node, or uses 'autoFocus' in a descendant, add
// state to Modal and only render the children when Modal
// is inserted in the DOM tree.
modalRoot.appendChild(this.el);
}
componentWillUnmount() {
modalRoot.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el,
);
}
三 . 使用注意
实现createPortals中的dom节点必须是真实的节点,不可以是虚拟节点