React的Transaction浅析
1.两个示例
- 示例1
let SonClass = React.createClass({
render: function(){
console.log("render", this.props.num);
return null;
},
componentDidMount: function(){
console.log('componentDidMount', this.props.num);
}
});
let FatherClass = React.createClass({
render:function(){
return (
<div>
<SonClass num="one" />
<SonClass num="two" />
</div>
)
}
});
ReactDOM.render( <FatherClass /> ,
document.getElementById("test")
);
输出为
render *2
componentDidMount *2
- 示例2
let React = require('react');
let ReactDOM = require('react-dom');
let Hello = React.createClass({
getInitialState: function() {
return {
clicked: 0
};
},
handleClick: function() {
this.setState({
clicked:this.state.clicked + 1
});
this.setState({
clicked: this.state.clicked + 1
});
},
render: function() {
return <button onClick = {
this.handleClick
} > {
this.state.clicked
} </button>;
}
});
ReactDOM.render( <Hello /> ,
document.getElementById("test")
);
点击后this.state.clicked递增1,而不是递增2。
2.解释
首先介绍React的Transaction。
其源码在React/lib/Transaction.js。
Transaction就是给需要执行的方法fn用wrapper封装了 initialize 和 close 方法。且支持多次封装。再通过 Transaction 提供的 perform 方法执行。 perform执行前,调用所有initialize 方法。perform 方法执行后,调用所有close方法。
Transaction的use case是
- Preserving the input selection ranges before/after reconciliation.
Restoring selection even in the event of an unexpected error. - Deactivating events while rearranging the DOM, preventing blurs/focuses,
while guaranteeing that afterwards, the event system is reactivated. - Flushing a queue of collected DOM mutations to the main UI thread after a
reconciliation takes place in a worker thread. - Invoking any collected
componentDidUpdatecallbacks after rendering new
content. - (Future use case): Wrapping particular flushes of the
ReactWorkerqueue
to preserve thescrollTop(an automatic scroll aware DOM). - (Future use case): Layout calculations before and after DOM updates.
示例一,对应的是第4点use case。整个生命周期就是一个Transaction,在Transaction执行期间,componentDidUpdate方法被推入一个队列中。DOM reconciliation后,再调用队列中的所有componentDidUpdate。
示例二,对应的是第3点use case。react的事件回调也是一个Transaction。handleClick里面的this.setState不会马上生效,而是先通过 ReactUpdates.batchedUpdate 方法存入临时队列。所以每次setState时,拿到的this.state.clicked都是初始值。直到transaction 完成,通过ReactUpdates.flushBatchedUpdates方法进行UI更新。
更详细的流程参考此图

3.参考文章(强烈推荐去看)
http://undefinedblog.com/what-happened-after-set-state/
http://zhuanlan.zhihu.com/purerender/20328570
React的Transaction浅析的更多相关文章
- React虚拟DOM浅析
在Web开发中,需要将数据的变化实时反映到UI上,这时就需要对DOM进行操作,但是复杂或频繁的DOM操作通常是性能瓶颈产生的原因,为此,React引入了虚拟DOM(Virtual DOM)的机制. 什 ...
- React生命周期浅析
引言 关于React的生命周期API,官网,有着详细说明.但在实际写代码的过程中,这些说明不能解决所有的疑惑. 所以我列举了一些编码中常见用例,供大家参考. 示例代码如下 /* use case 1. ...
- 使用Redux管理React数据流要点浅析
在图中,使用Redux管理React数据流的过程如图所示,Store作为唯一的state树,管理所有组件的state.组件所有的行为通过Actions来触发,然后Action更新Store中的stat ...
- react diff算法浅析
diff算法作为Virtual DOM的加速器,其算法的改进优化是React整个界面渲染的基础和性能的保障,同时也是React源码中最神秘的,最不可思议的部分 1.传统diff算法计算一棵树形结构转换 ...
- React Native初探
前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...
- React 组件性能优化
React组件性能优化 前言 众所周知,浏览器的重绘和重排版(reflows & repaints)(DOM操作都会引起)才是导致网页性能问题的关键.而React虚拟DOM的目的就是为了减少浏 ...
- [React] 10 - Tutorial: router
Ref: REACT JS TUTORIAL #6 - React Router & Intro to Single Page Apps with React JS Ref: REACT JS ...
- 【优质】React的学习资源
React的学习资源 github 地址: https://github.com/LeuisKen/react-collection https://github.com/reactnativecn/ ...
- React Native指南汇集了各类react-native学习资源、开源App和组件
来自:https://github.com/ele828/react-native-guide React Native指南汇集了各类react-native学习资源.开源App和组件 React-N ...
随机推荐
- Session 知识点再整理(二) 自定义 Session 存储机制
对于访问量大的网站,用默认的 Session 存储方式(以文件存储)不适合,因为文件的 I/O 开销会非常大,另外 Session 机制本身使 Session 不能跨机访问,在 Web 集群中无法达到 ...
- iOS审核秘籍】提审资源检查大法
iOS审核秘籍]提审资源检查大法 2015/11/27 阅读(752) 评论(1) 收藏(6) 加入人人都是产品经理[起点学院]产品经理实战训练营,BAT产品总监手把手带你学产品点此查看详情! 本篇主 ...
- LeetCode Range Sum Query 2D - Mutable
原题链接在这里:https://leetcode.com/problems/range-sum-query-2d-mutable/ 题目: Given a 2D matrix matrix, find ...
- cocos2dx 3.x(场景(层)的生命周期)
//进入当前层初第一步始化层调用 bool GameScence::init() { if( !void init() ) { returnfalse; } log("进入当前层初第一步始化 ...
- cocoa pods报错The dependency `Reveal-iOS-SDK` is not used in any concrete target.
Podfile错误写法,会报错The dependency `Reveal-iOS-SDK` is not used in any concrete target. platform:ios,'7.0 ...
- apache php env build
from http://blog.csdn.net/yincg/article/details/8782364 1.1 系统说明Centos 6.2 (最小化安装)1.2 软件说明httpd-2.4. ...
- Leetcode: Longest Repeating Character Replacement && G 面经
Given a string that consists of only uppercase English letters, you can replace any letter in the st ...
- composer--------------今天遇到几个奇葩问题,记录一下
1.就是composer跟xdebug有冲突,每次用composer命令的时候都要报xdebug的错误,其实这个只要你去php的配置文件里面将xdebug注释掉就可以了,但是我注释掉了以后还是不行.找 ...
- Eclipse in Ubuntu16.04LTS Final Beta
#2016.03.30 在虚拟机Ubuntu16.04LTS上,用Eclipse编写运行Java,就目前而言,实在不是明智之举.卡顿极其厉害,还是在物理机上运行吧.那么继续Ubuntu的探索历程. 用 ...
- C++ 学习笔记(3) —— 內联函数
内联函数的用处: 用空间换取时间,在调用时不用每次都写调用的汇编. 什么时候内联: 比较小的函数:只有两三行 在循环里循环调用的函数 什么时候不内联: 比较大的函数,2.30行的 递归的函数