React的Transaction浅析

时间:2023-03-09 16:48:22
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是

  1. Preserving the input selection ranges before/after reconciliation.

    Restoring selection even in the event of an unexpected error.
  2. Deactivating events while rearranging the DOM, preventing blurs/focuses,

    while guaranteeing that afterwards, the event system is reactivated.
  3. Flushing a queue of collected DOM mutations to the main UI thread after a

    reconciliation takes place in a worker thread.
  4. Invoking any collected componentDidUpdate callbacks after rendering new

    content.
  5. (Future use case): Wrapping particular flushes of the ReactWorker queue

    to preserve the scrollTop (an automatic scroll aware DOM).
  6. (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更新。

更详细的流程参考此图

React的Transaction浅析

3.参考文章(强烈推荐去看)

http://undefinedblog.com/what-happened-after-set-state/

http://zhuanlan.zhihu.com/purerender/20328570