react 中组件Modal, Dialog 怎么挂载到body上了的?

本文探讨了在React中如何将Modal和Dialog组件挂载到body上,主要通过分析antd库依赖的rc-dialog实现。核心涉及ReactDOM的unstable_renderSubtreeIntoContainer和createPortal方法,解释了Model.confirm和message.info的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一些猜想

  • 因为支持组件式写法 ,肯定是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上面
  • 核心代码如下截图
    rc-dialog代码
    这里发现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

// 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
  };
}

待补充。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值