Rendering React components to the document body
React一个比较好用的功能是其简单的API,一个组件可以简单到一个return了组件结构的render函数。除了一个简单的函数之外,我们还有了一段有用且可复用的代码片段。
问题
不过有时候可能会受到限制。
特别是,实际上这个API返回的是一个没有限制dom挂载在何处的组件,这就使得一些popup组件比较困难去实现。如果父元素限制了oerflow为hidden。就像下面这个例子一样

实际上我们想要的是这样的:

解决
幸运的是有一种相当优雅的方式来达到目的,尽管该方式并不太常见。
作为每个人最早学习到的React方法之一,React.render大概如下:
ReactComponent render(
ReactElement element,
DOMElement container,
[function callback]
)
通常我们使用其来将整个应用挂载到一个DOM元素下面。令人愉悦的是,其不仅仅局限于此,实际上我们可以在一个组件中通过React.render将另一个组件挂载到完全不同的DOM节点。作为组件的render函数其本身必须保持纯净(不能改变state或者和dom进行交互) ,否则的话我们应该在componentDidUpdate或者componentDidMount里面进行操作。另外我们需要确保当其父组件卸载的时,所有已经被渲染的组件可以同样正确的被卸载。
兼顾以上几点,我们可以构建一个解决相关问题的组件。
/**
* 注:该文章较早,与dom相关的方法已经被拆分到ReactDom中
*/
var RenderInBody = React.createClass({
componentDidMount: function() {
// 创建待弹出元素的挂载节点
this.popup = document.createElement("div");
// 添加至document.body
document.body.appendChild(this.popup);
this._renderLayer();
},
componentDidUpdate: function() {
// 更新时
this._renderLayer();
},
componentWillUnmount: function() {
// 从挂载节点上清除popup元素
// (React元素使用该方法,清除的不仅是dom还有state和事件)
React.unmountComponentAtNode(this.popup);
// 移除挂载节点
document.body.removeChild(this.popup);
},
_renderLayer: function() {
// 将children挂载到 popup节点
React.render(this.props.children, this.popup);
}
render: function() {
// 渲染一个占位符。
return React.DOM.div(this.props);
}
});
然后无论何时我们想要将父组件的dom转换到document.body上时,需要做的只是将我们组件的输出包括在RenderInBody组件里,像下面这样就行了:
var Dialog = React.createClass({
render: function() {
// 弹框组件
var dialogPopup = <DialogPopup {...this.props} />;
// 包括该组件
return (
<RenderInBody>{dialogPopup}</RenderInBody>
);
}
});
结束语
原文地址
Rendering React components to the document body
本文翻自Rendering React components to the document body这就是所谓的render to body模式.
对于那些popup即弹出层组件,如果将其直接挂载在父元素下面,可能会存在被父元素影响的可能。
为了解决这样的问题,作者提供了一种思路,既然可能会受直接父元素影响,那么直接跨过去,挂载到body上不就解决这个问题了。
这就是本文的用意所在。
感谢原作者,学习到了一种更优雅的处理方式,原本自己写的Dialog之类的组件,确实是挂到直接父元素下面,即写在哪出现在哪,很容易受到其他元素影响。
好文共赏,与诸君共勉。
Rendering React components to the document body的更多相关文章
- React Components之间的通信方式了解下
先来几个术语: 官方 我的说法 对应代码 React element React元素 let element=<span>A爆了</span> Component 组件 cla ...
- [Poi] Use Markdown as React Components by Adding a Webpack Loader to Poi
Poi ships with many webpack loaders included, but you may run into scenarios where you'll need to cu ...
- React components render order All In One
React components render order All In One components render order / components lifecycle DOM tree ren ...
- [React] Styling React Components With Aphrodite
Aphrodite is a library styling React components. You get all the benefits of inline styles (encapsul ...
- React Components Template
React Components Template "use strict"; /** * * @author xgqfrms * @license MIT * @copyrigh ...
- [React] Create and import React components with Markdown using MDXC
In this lesson I demonstrate how to use the library MDXC to create and import React components with ...
- [React] Recompose: Theme React Components Live with Context
SASS Bootstrap allows us to configure theme or branding variables that affect all components (e.g. P ...
- [React] Intro to inline styles in React components
React lets you use "inline styles" to style your components; inline styles in React are ju ...
- [React] Extracting Private React Components
we leverage private components to break our render function into more manageable pieces without leak ...
随机推荐
- ES6笔记
/** * Created by Administrator on 2017/4/13. */ /*---------------------Es6编码规范---------------------* ...
- SpringBoot图片上传(一)
简单描述:点击上传文件的图标,上传文件,上传成功后,图标编程上传的图片. 吐槽:文件上传下载这种东西,总是感觉莫名的虚-_-|| 也不知道是造了什么孽,(其实就是IO File这一块的知识了解的不太 ...
- laravel 5.6
compact() 建立一个数组,包括变量名和它们的值 打印结果: starts_with() 函数判断给定的字符串的开头是否是指定值
- 如何在地址栏(title标签里)和收藏夹里 加上网站的标志ICO、LOGO图片
第一步:首先你必须要制作一个看起来既清楚又容易辨识的.ico格式的小图片. 我们将图标的大小定义为16x16 像素.此外在制作图形文件的时候,你可能需要把色盘设定成只使用标准的 16 色 Window ...
- C++ shut down a computer
前阵子有朋友问我,怎么用C语言写一个小程序,控制电脑关机.这个我真的不懂,这几天闲着,就上网搜了搜,整理一下. IDE: Code::Blocks 16.01 操作系统:Windows 7 x64 # ...
- Python中对文件和目录的操作
用到的核心模块有:os shutil 文件的创建:f = open("文件名", "w") 注:如果涉及到乱码问题需要在后面加上encoding=&quo ...
- 眼底血管分割训练函数(SVM,Adaboost)
# -*- coding: utf-8 -*- import numpy as np from sklearn import svm from sklearn.model_selection impo ...
- C# 不使用递归遍历目录树中的文件和文件夹
public class StackBasedIteration { static void Main(string[] args) { // Specify the starting folder ...
- webpack+vue打包之后输出配置文件修改接口文件
用vue-cli构建的项目通常是采用前后端分离的开发模式,也就是前端与后台完全分离,此时就需要将后台接口地址打包进项目中,but,难道我们只是改个接口地址也要重新打包吗?当然不行了,那就太麻烦了,怎么 ...
- pycaffe训练的完整组件示例
pycaffe训练的完整组件示例 为什么写这篇博客 1. 需要用到pycaffe 因为用到的开源代码基于Caffe:要维护的项目基于Caffe.基本上是用Caffe的Python接口. 2. 训练中想 ...