React如何将组件渲染到指定DOM节点详解

发布时间 - 2026-01-11 03:09:34    点击率:

前言

众所周知React优点之一就是他的API特别简单。通过render 方法返回一个组件的基本结构,如同一个简单的函数,就可以得到一个可以复用的react组件。但是有时候还是会有些限制的,尤其是他的API中,不能控制组件所应该渲染到的DOM节点,这就让一些弹层组件很难控制。当父元素设置为overflow:hidden 的时候,问题就会出现了。

例如就像下面的这样:

我们实际期待的效果是这样的:

幸运的是,虽然不是很明显,但有一个相当优雅的方式来绕过这个问题。我们学到的第一个react函数是render 方法,他的函数签名是这样的:

ReactComponent render(
 ReactElement element,
 DOMElement container,
 [function callback]
)

通常情况下我们使用该方法将整个应用渲染到一个DOM节点中。好消息是该方法并不仅仅局限于此。我们可以在一个组件中,使用ReactDom.render 方法将另一个组件渲染到一个指定的DOM 元素中。作为一个组件的render 方法,其必须是纯净的(例如:不能改变state或者与DOM交互).所以我们需要在componentDidUpdate 或者 componentDidMount 中调用ReactDom.render 方法。

另外我们需要确保在父元素被卸载的时候,改组件也要被卸载掉.

整理下,我们得到下面的一个组件:

import React,{Component} from 'react';
import ReactDom from 'react-dom';
export default class RenderInBody extends Component{
 constructor(p){
  super();
 }
 componentDidMount(){//新建一个div标签并塞进body
  this.popup = document.createElement("div");
  document.body.appendChild(this.popup);
  this._renderLayer();
 }
 componentDidUpdate() {
  this._renderLayer();
 }
 componentWillUnmount(){//在组件卸载的时候,保证弹层也被卸载掉
  ReactDom.unmountComponentAtNode(this.popup);
  document.body.removeChild(this.popup);
 }
 _renderLayer(){//将弹层渲染到body下的div标签
  ReactDom.render(this.props.children, this.popup);
 }
 render(){
  return null;
 }
}

总结下就是:

在componentDidMount的时候手动向body内塞一个div标签,然后使用ReactDom.render 将组件渲染到这个div标签

当我们想把组件直接渲染到body上的时候,只需要在该组件的外面包一层RenderInBody 就可以了.

export default class Dialog extends Component{
 render(){
  return {
   <RenderInBody>i am a dialog render to body</RenderInBody>
  }
 }
}

译者增加:

将以上组件改造一下,我们就可以向指定的dom节点中渲染和卸载组件,并加上位置控制,如下:

//此组件用于在body内渲染弹层
import React,{Component} from 'react'
import ReactDom from 'react-dom';
export default class RenderInBody extends Component{
 constructor(p){
  super(p);
 }
 componentDidMount(){
  /**
  popupInfo={
   rootDom:***,//接收弹层组件的DOM节点,如document.body
   left:***,//相对位置
   top:***//位置信息
  }
  */
  let {popupInfo} = this.props; 
  this.popup = document.createElement('div');
  this.rootDom = popupInfo.rootDom;  
  this.rootDom.appendChild(this.popup);
  //we can setAttribute of the div only in this way
  this.popup.style.position='absolute';
  this.popup.style.left=popupInfo.left+'px';
  this.popup.style.top=popupInfo.top+'px';
  this._renderLayer()
 }
 componentDidUpdate() {
  this._renderLayer();
 }
 componentWillUnmount(){
  this.rootDom.removeChild(this.popup);
 }
 _renderLayer(){
  ReactDom.render(this.props.children, this.popup);
 }
 render(){
  return null;
 }
}

注:位置获取和根结点判断函数

export default (dom,classFilters)=> {
 let left = dom.offsetLeft,
  top = dom.offsetTop + dom.scrollTop,
  current = dom.offsetParent,
  rootDom = accessBodyElement(dom);//默认是body
 while (current !=null ) {
  left += current.offsetLeft;
  top += current.offsetTop;
  current = current.offsetParent;
  if (current && current.matches(classFilters)) {
   rootDom = current;
   break;
  }
 }
 return { left: left, top: top ,rootDom:rootDom};
}
/***
1. dom:为响应弹层的dom节点,或者到该dom的位置后,可以做位置的微调,让弹层位置更佳合适
*
2. classFilters:需要接收弹层组件的DOM节点的筛选类名
/

原文地址

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。


# reactjs  # 获取组件dom  # react  # 获取dom节点  # 重新渲染组件  # React组件通信之路由传参(react-router-dom)  # react四种组件中DOM样式设置方式详解  # 详解React获取DOM和获取组件实例的方式  # 就可以  # 是这样  # 的是  # 就会  # 就像  # 第一个  # 尤其是  # 很难  # 也要  # 卸载掉  # 只需  # 这个问题  # 要在  # 我们可以  # 这就  # 作为一个  # 当我们  # 这篇文章  # 想把  # 谢谢大家 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 高端云建站费用究竟需要多少预算?  微信公众帐号开发教程之图文消息全攻略  如何用好域名打造高点击率的自主建站?  如何在阿里云完成域名注册与建站?  Firefox Developer Edition开发者版本入口  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  如何挑选最适合建站的高性能VPS主机?  jQuery中的100个技巧汇总  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】  Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率  美食网站链接制作教程视频,哪个教做美食的网站比较专业点?  PHP正则匹配日期和时间(时间戳转换)的实例代码  高端建站三要素:定制模板、企业官网与响应式设计优化  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  Laravel如何使用Eloquent进行子查询  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  C++时间戳转换成日期时间的步骤和示例代码  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  原生JS获取元素集合的子元素宽度实例  如何在企业微信快速生成手机电脑官网?  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  微信小程序 配置文件详细介绍  Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程  微信推文制作网站有哪些,怎么做微信推文,急?  Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?  Laravel怎么在Controller之外的地方验证数据  谷歌Google入口永久地址_Google搜索引擎官网首页永久入口  如何构建满足综合性能需求的优质建站方案?  JavaScript如何实现错误处理_try...catch如何捕获异常?  Laravel中的Facade(门面)到底是什么原理  Laravel如何操作JSON类型的数据库字段?(Eloquent示例)  Laravel如何使用Blade组件和插槽?(Component代码示例)  音乐网站服务器如何优化API响应速度?  5种Android数据存储方式汇总  Laravel如何处理文件下载请求?(Response示例)  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  如何在云主机上快速搭建网站?  如何注册花生壳免费域名并搭建个人网站?  php增删改查怎么学_零基础入门php数据库操作必知基础【教程】  如何用美橙互联一键搭建多站合一网站?  php8.4header发送头信息失败怎么办_php8.4header函数问题解决【解答】  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  如何彻底删除建站之星生成的Banner?  详解Android图表 MPAndroidChart折线图  大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?