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
2javascript

  • 示例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。java

2.解釋

首先介紹React的Transaction。
其源碼在React/lib/Transaction.js。
Transaction就是給須要執行的方法fn用wrapper封裝了 initialize 和 close 方法。且支持屢次封裝。再經過 Transaction 提供的 perform 方法執行。 perform執行前,調用全部initialize 方法。perform 方法執行後,調用全部close方法。react

Transaction的use case是app

  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。dom

示例二,對應的是第3點use case。react的事件回調也是一個Transaction。handleClick裏面的this.setState不會立刻生效,而是先經過 ReactUpdates.batchedUpdate 方法存入臨時隊列。因此每次setState時,拿到的this.state.clicked都是初始值。直到transaction 完成,經過ReactUpdates.flushBatchedUpdates方法進行UI更新。
更詳細的流程參考此圖
react事件回調核心流程ui

3.參考文章(強烈推薦去看)

http://undefinedblog.com/what-happened-after-set-state/
http://zhuanlan.zhihu.com/purerender/20328570this

相關文章
相關標籤/搜索