setState 更新機制學習筆記

一、setState不會當即改變state的值
二、setState會經過觸發組件的更新來觸發重繪
setState依次觸發如下4個組件的生命週期
1)shouldComponentUpdate(被調用時,state尚未更新,若是返回false,不會再觸發其餘生命周 期,可是state依然會被更新)
2)componentWillUpdate(被調用時state尚未被更新)
3)render(調用時state已經被更新)
4)componentDidUpdate
三、屢次連續的setState會進行合併react

//兩次連續setState
this.setState({name: ‘xiaoming’})
this.setState({age: 24})
//至關於
this.setState({name: ‘xiaoming’, age: 24})

state源碼流程

調用this.setState其實是調用this.updater.enqueueSetState,每一個ReactComponent對象在運行時都會被注入updater屬性,咱們經過打印Component實例可查看,如圖所示:
圖片描述數組

知道了這個屬性,setState源碼就十分清晰了this

ReactComponent.prototype.setState = (partialState, callback) => {
    // this是組件實例
    // 將setState、callbackfen放入updater的隊列中
    this.updater.enqueueSetState(this, partialState)
    if(callback) {
        this.updater.enqueueCallback(this, callback, ’setState')
    }
}

下面看一下真是調用的enqueueSetState方法spa

enqueueSetState: (publicInstance, partailState) {
    // 組件實例有一個_reactInternalInstance屬性,能夠當作獲取該屬性
    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, ’setState’)
    // 初始化實例的待更新隊列
    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = [])   
    queue.push(partailState)
    enqueueUpdate(internalInstance)
}

enqueueSetState內調用的enqueueUpdateprototype

enqueueUpdate: (component) {
    //若是不是處於批量建立/更新組件的階段,就更新當前組件
    // batchingStrategy是ReactDefaultBatchingStrategy對象的引用
    if(!batchingStrategy.isBatchingUpdates) {
        batchingStrategy.batchedUpdates(enqueueUpdate, component)
        return;
    }
    // 若是處於批量更新階段,則放進髒數組中等待,等待更新
    dirtyComponents.push(component)
}

batchingStrategy.isBatchingUpdates,在react中只有兩個地方被更新,code

  • 自身的batchedUpdates方法,開啓批量更新
  • 事務的close方法,設置爲false
var ReactDefaultBatchingStrategy = {
    //標記是否處於批量更新/新建階段,默認是false
    isBatchingUpdates: false,
    //開啓批量更新方法
    batchedUpdates: function(callback, a, b, c, d, e) {
        var alreadyBatchUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
        ReactDefaultBatchingStrategy.isBatchingUpdates = true;
        //已經開啓了批量更新,調用callback回調,就是enqueueUpdate方法,進去從新等待
        if(alreadyBatchUpdates) {
            return callback(a, b, c, d, e)
        }
        // 不然開啓事務,進行批量更新
        Return transaction.perform(callback, null, a, b, c, d, e)
    }
}
相關文章
相關標籤/搜索