1、setState不会立即改变state的值
2、setState会通过触发组件的更新来触发重绘
setState依次触发以下4个组件的生命周期
1)shouldComponentUpdate(被调用时,state还没有更新,如果返回false,不会再触发其他生命周 期,但是state依然会被更新)
2)componentWillUpdate(被调用时state还没有被更新)
3)render(调用时state已经被更新)
4)componentDidUpdate
3、多次连续的setState会进行合并
//两次连续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源码就十分清晰了
ReactComponent.prototype.setState = (partialState, callback) => {
// this是组件实例
// 将setState、callbackfen放入updater的队列中
this.updater.enqueueSetState(this, partialState)
if(callback) {
this.updater.enqueueCallback(this, callback, ’setState')
}
}
下面看一下真是调用的enqueueSetState方法
enqueueSetState: (publicInstance, partailState) {
// 组件实例有一个_reactInternalInstance属性,可以看成获取该属性
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, ’setState’)
// 初始化实例的待更新队列
var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = [])
queue.push(partailState)
enqueueUpdate(internalInstance)
}
enqueueSetState内调用的enqueueUpdate
enqueueUpdate: (component) {
//如果不是处于批量创建/更新组件的阶段,就更新当前组件
// batchingStrategy是ReactDefaultBatchingStrategy对象的引用
if(!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component)
return;
}
// 如果处于批量更新阶段,则放进脏数组中等待,等待更新
dirtyComponents.push(component)
}
batchingStrategy.isBatchingUpdates,在react中只有两个地方被更新,
- 自身的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)
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。