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)
    }
}
相关文章
相关标签/搜索