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的更多相关文章

  1. React Components之间的通信方式了解下

    先来几个术语: 官方 我的说法 对应代码 React element React元素 let element=<span>A爆了</span> Component 组件 cla ...

  2. [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 ...

  3. React components render order All In One

    React components render order All In One components render order / components lifecycle DOM tree ren ...

  4. [React] Styling React Components With Aphrodite

    Aphrodite is a library styling React components. You get all the benefits of inline styles (encapsul ...

  5. React Components Template

    React Components Template "use strict"; /** * * @author xgqfrms * @license MIT * @copyrigh ...

  6. [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 ...

  7. [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 ...

  8. [React] Intro to inline styles in React components

    React lets you use "inline styles" to style your components; inline styles in React are ju ...

  9. [React] Extracting Private React Components

    we leverage private components to break our render function into more manageable pieces without leak ...

随机推荐

  1. ES6笔记

    /** * Created by Administrator on 2017/4/13. */ /*---------------------Es6编码规范---------------------* ...

  2. SpringBoot图片上传(一)

    简单描述:点击上传文件的图标,上传文件,上传成功后,图标编程上传的图片. 吐槽:文件上传下载这种东西,总是感觉莫名的虚-_-||  也不知道是造了什么孽,(其实就是IO File这一块的知识了解的不太 ...

  3. laravel 5.6

    compact() 建立一个数组,包括变量名和它们的值 打印结果: starts_with() 函数判断给定的字符串的开头是否是指定值

  4. 如何在地址栏(title标签里)和收藏夹里 加上网站的标志ICO、LOGO图片

    第一步:首先你必须要制作一个看起来既清楚又容易辨识的.ico格式的小图片. 我们将图标的大小定义为16x16 像素.此外在制作图形文件的时候,你可能需要把色盘设定成只使用标准的 16 色 Window ...

  5. C++ shut down a computer

    前阵子有朋友问我,怎么用C语言写一个小程序,控制电脑关机.这个我真的不懂,这几天闲着,就上网搜了搜,整理一下. IDE: Code::Blocks 16.01 操作系统:Windows 7 x64 # ...

  6. Python中对文件和目录的操作

    用到的核心模块有:os   shutil 文件的创建:f = open("文件名", "w")  注:如果涉及到乱码问题需要在后面加上encoding=&quo ...

  7. 眼底血管分割训练函数(SVM,Adaboost)

    # -*- coding: utf-8 -*- import numpy as np from sklearn import svm from sklearn.model_selection impo ...

  8. C# 不使用递归遍历目录树中的文件和文件夹

    public class StackBasedIteration { static void Main(string[] args) { // Specify the starting folder ...

  9. webpack+vue打包之后输出配置文件修改接口文件

    用vue-cli构建的项目通常是采用前后端分离的开发模式,也就是前端与后台完全分离,此时就需要将后台接口地址打包进项目中,but,难道我们只是改个接口地址也要重新打包吗?当然不行了,那就太麻烦了,怎么 ...

  10. pycaffe训练的完整组件示例

    pycaffe训练的完整组件示例 为什么写这篇博客 1. 需要用到pycaffe 因为用到的开源代码基于Caffe:要维护的项目基于Caffe.基本上是用Caffe的Python接口. 2. 训练中想 ...