React拾遗(下)
reconciliation(协调算法)
react用于更新DOM的算法。基于两点假设,实现了一个启发的O(n)算法:
- 两个不同类型的元素将产生不同的树。
- 通过渲染器附带
key属性,开发者可以示意哪些子元素可能是稳定的。
元素的不同类型
当对比两棵树时,React首先比较两个根节点。每当根元素有不同类型,React将卸载旧树并重新构建新树。
当树被卸载,旧的DOM节点将被销毁。组件实例将会接收到componentWillUnmount()方法。当构建一棵新树,新的DOM节点被插入到DOM中。组件实例将接收到componentWillMount()以及之后的componentDidMount()。任何有关旧树的状态都将被丢弃。
例如,在进行对比:
<div>
<Counter />
</div>
<span>
<Counter />
</span>
这将会销毁旧的Counter并重装新节点。
相同类型的DOM元素
当比较两个相同类型的React DOM元素时,React则会观察二者的属性,保持相同的底层DOM节点,并仅更新变化的属性。(比如说变化的类名、样式等)
在处理完DOM元素后,React递归其子元素。
递归子节点
默认时。当递归DOM节点的子节点,React仅在同一时间点递归两个子节点列表,并在有不同时产生一个变更。
例如,当在子节点末尾增加一个元素,两棵树的转换效果很好:
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
React将会匹配两棵树的
,并匹配两棵树的
节点,并插入
节点树。
若原生实现,在开始插入元素会使得性能更棘手。例如,两棵树的转换效果则比较糟糕:
<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>
React会调整每个子节点,而非意识到可以完整保留
和
子树。低效成了一个问题。
Keys
为解决该问题,React支持了一个key属性。当子节点有key时,React使用key来匹配原本树的子节点和新树的子节点。例如,增加一个key在之前效率不高的样例中能让树的转换变得高效:
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
现在React知道带有'2014'的key的元素是新的,并仅移动带有'2015'和'2016'的key的元素。
权衡
由于React依赖于该启发式算法,若其背后的假设没得到满足,则其性能将会受到影响:
- 算法无法尝试匹配不同组件类型的子元素。若你发现两个输出非常相似的组件类型交替出现,你可能希望使其成为相同类型。实践中,我们并非发现这是一个问题。
- Keys应该是稳定的,可预测的,且唯一的。不稳定的key(类似由
Math.random()生成的)将使得大量组件实例和DOM节点进行不必要的重建,使得性能下降并丢失子组件的状态。
Portals
Portals 提供了一种很好的将子节点渲染到父组件以外的 DOM 节点的方式。
ReactDOM.createPortal(child, container)
第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或碎片。第二个参数(container)则是一个 DOM 元素。
用法
通常讲,当你从组件的 render 方法返回一个元素,该元素仅能装配 DOM 节点中离其最近的父元素
render() {
// React mounts a new div and renders the children into it
return (
<div>
{this.props.children}
</div>
);
}
然而,有时候将其插入到 DOM 节点的不同位置也是有用的:
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,
);
}
对于 portal 的一个典型用例是当父组件有 overflow: hidden 或 z-index 样式,但你需要子组件能够在视觉上“跳出(break out)”其容器。例如,对话框、hovercards以及提示框。
通过 Portals 进行事件冒泡
尽管 portal 可以被放置在 DOM 树的任何地方,但在其他方面其行为和普通的 React 子节点行为一致。如上下文特性依然能够如之前一样正确地工作,无论其子节点是否是 portal,由于 portal 仍存在于 React 树中,而不用考虑其在 DOM 树中的位置。
这包含事件冒泡。一个从 portal 内部会触发的事件会一直冒泡至包含 React 树 的祖先。
React拾遗(下)的更多相关文章
- [RN] React Native 下拉放大动画
React Native 下拉放大动画 经测试,无法运行 https://www.jianshu.com/p/1c960ad75020
- [RN] React Native 下实现底部标签(支持滑动切换)
上一篇文章 [RN] React Native 下实现底部标签(不支持滑动切换) 总结了不支持滑动切换的方法,此篇文章总结出 支持滑动 的方法 准备工作之类的,跟上文类似,大家可点击上文查看相关内容. ...
- react框架下,在页面内加载显示PDF文件,关于react-pdf-js的使用注意事项
react框架下,在页面内加载显示PDF文件,关于react-pdf-js的使用注意事项 之前做了一个需求,在注册账号的时候,让用户同意服务条款, 服务条款是一个PDF文件, 这就需要在react内加 ...
- React视角下的轮播图
天猫购物网站最显眼的就是轮播图了.我在学习一样新js库,一个新框架或新的编程思想的时候,总是感叹"入门必做选项卡,进阶须撸轮播图."作为一个React组件,它是状态操控行为的典型, ...
- react native下android开发环境搭建
关于react native环境搭建我也是参考这篇文章的,但我这里就出现了很多在这篇文章里没有出现的问题,也是坑比较多.但最后在一位大神的帮助下还是成功运行了. 1.第一个坑就是有些文件下载需要VPN ...
- [RN] React Native 下实现底部标签(不支持滑动切换)
底部标签是现在App的基本菜单实现 下面分别用 createBottomTabNavigator 和 createMaterialBottomTabNavigator 两种方法分别实现底部菜单 但此两 ...
- React拾遗(上)
JSX代表Objects Babel转义器会把JSX转换成一个名为React.createElement()的方法调用. 下面两种代码的作用是完全相同的: const element = ( < ...
- [RN] React Native 下列表 FlatList 和 SectionList
1.FlatList FlatList组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同. FlatList更适于长列表数据,且元素个数可以增删.和ScrollView不同的是,Fla ...
- react ie10下报错
解决办法: 加 promise polyfill 参考地址:http://hao.jser.com/archive/12066/
随机推荐
- 开源框架---tensorflow c++ API中./configure步骤细节
u@u160406:~/tf1.13/tensorflow$ git checkout r1.13 分支 r1.13 设置为跟踪来自 origin 的远程分支 r1.13.切换到一个新分支 'r1.1 ...
- Nginx练习练习玩玩
Date:2019-11-9 读前思考: 对于NGINX,一般会问什么? 面试官会从哪方面入手? 面试官到底想考察什么? 你做好准备了吗? 如果对于初学者,往往可以通过面试题来提升对某一个技术的了解和 ...
- linux网络编程之system v消息队列(二)
今天继续学习system v消息队列,主要是学习两个函数的使用,开始进入正题: 下面则开始用代码来使用一下该发送函数: 在运行之前,先查看一下1234消息队列是否已经创建: 用上次编写的查看消息队列状 ...
- .NET Core 初体验
.NET Core 作为微软的开源项目,neter 们对之的期待还是挺大的. 以前也看过,接触过,摸索建了几个示例项目,今天就罗列下自己的初体验. .NET Core 安装.帮助等 安装的话,直接官网 ...
- ASP.NET MVC 入门5、View与ViewData
View建立时有MVC View Page 和 MVC View Content Page两种类型, 前者为标准View, 后者为可继承Master母版页的View. Asp.Net MVC 默认使用 ...
- Java实习生面试题分享
1.Java有那些基本数据类型,String是不是基本数据类型,他们有何区别. Java语言提供了八种基本类型: 六种数字类型(四个整数型,两个浮点型) 字节型byte 8位 短整型short 16位 ...
- 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem——哈希表&&二进制枚举
题意 有长度为 $n$($1\leq n\leq 36$)的数列,给出 $s$,求和为 $s$ 的子集,保证子集存在且唯一. 分析 答案肯定是来自左右半边两部分组成的. 如果我们用哈希表存一半,计算另 ...
- nginx动静分离配置
动静分离: 所谓动静分离指的是当访问静态资源时,路由到一台静态资源服务器,当访问是非静态资源时,路由到另外一台服务器 静态资源配置: 如配置如下location 表示url为 /static/*.x ...
- Mac 升级 Python2.7 到 Python3.5
1.去 Python 官网下载一个版本的包 https://www.python.org/downloads/mac-osx/ 2.安装之后,去 /Library/Frameworks/Python ...
- SIGAI机器学习第十六集 支持向量机3
讲授线性分类器,分类间隔,线性可分的支持向量机原问题与对偶问题,线性不可分的支持向量机原问题与对偶问题,核映射与核函数,多分类问题,libsvm的使用,实际应用 大纲: 多分类问题libsvm简介实验 ...