react 中组件Modal, Dialog 怎么挂载到body上了的?
一些猜想
- 因为支持组件式写法 ,肯定是React中一些api,把modal,dialog的元素append到body里面的
function UserDefinedComponent {
return (
<div>
<Modal_or_Dialog {...someProps}>
...一些react元素
</Modal_or_Dialog>
</div>
)
}
看antd modal的代码如何实现的
- 找了一会发现antd依赖rc-dialog 这个库,那我们就接着看rc-dialog这个库如何把元素放到body上面
- 核心代码如下截图
这里发现react 16和react 16以前的实现还有差异
1. ReactDOM.unstable_renderSubtreeIntoContainer
先看下react 16以前的实现,我们顺着依赖关系可以找到
rc-util/lib/ContainerRender.js这个文件, 最好找到下面这个api, 我们可以看到一些这个方法的介绍。
ReactDOM.unstable_renderSubtreeIntoContainer
/**
* renderSubtreeIntoContainer
* Renders a React component into the DOM in the supplied `container`.
*
* If the React component was previously rendered into `container`, this will
* perform an update on it and only mutate the DOM as necessary to reflect the
* latest React component.
*
* @param {ReactComponent} parentComponent The conceptual parent of this render tree.
* @param {ReactElement} nextElement Component element to render.
* @param {DOMElement} container DOM element to render into.
* @param {?function} callback function triggered on completion
* @return {ReactComponent} Component instance rendered in `container`.
*/
2.ReactDOM.createPortal
- react portals相关介绍
ReactDOM.createPortal(this.props.children, this._container);
// Portals provide a first-class way to render children into a DOM node that exists
// outside the DOM hierarchy of the parent component.
// 具体用法如下
ReactDOM.createPortal(child, container)
// render函数
render() {
// React does *not* create a new div. It renders the children into `domNode`.
// `domNode` is any valid DOM node, regardless of its location in the DOM.
return ReactDOM.createPortal(
this.props.children,
domNode
);
}
Model.confirm,message.info的实现
- 相关代码如下,只要使用了
ReactDOM.render、React.createElement
这两个api
function confirm(config) {
var div = document.createElement('div');
document.body.appendChild(div);
var currentConfig = _extends({}, config, {
close: close,
visible: true
});
function close() {
}
function update(newConfig) {
currentConfig = _extends({}, currentConfig, newConfig);
render(currentConfig);
}
function destroy() {
}
function render(props) {
ReactDOM.render(React.createElement(ConfirmDialog, props), div);
}
render(currentConfig);
destroyFns.push(close);
return {
destroy: close,
update: update
};
}
待补充。。。