目录
1. 调用setState时候并没有立即执行,而是触发Updater更新,将callback函数和nextState进行先添加操作
setState总体思路:
- setState执行时,会讲partialSate添加到队列pendingState中
- updateComponent负责遍历pendingState整合新的state
- forceUpdate将一周期更新控制关闭, 进行此周期新旧vnode的diff对比及实际更新操作
1. 调用setState时候并没有立即执行,而是触发Updater更新,将callback函数和nextState进行先添加操作
setState函数逻辑
setState(newState) {
// 每次执行事件都会自动添加canMerge,用来合并state数据,然后等函数调用执行完,将canMerge=false,进行统一更新
if (this.canMerge) {
this.updateQueue.push(newState)
return
}
// 下面是真正的更新: dom-diff, lifeCycle...
...
}
例如:
g() {
this.setState({
age: 18
})
this.setState({
color: 'black‘
})
}
f() {
this.setState({
name: 'yank'
})
this.g()
}
会被react整理标记成
g() {
this.setState({
age: 18
})
this.setState({
color: 'black‘
})
}
f() {
this.canMerge = true
this.setState({
name: 'yank'
})
this.g()
this.canMerge = false
// 通过this.updateQueue合并出finalState
const finalState = ...
// 此时canMerge 已经为false 故而走入实际更新逻辑
this.setState(finaleState)
}
2.更新操作的大致思路
class Updater {
constructor(instance) {
this.pendingCallback = []; // callback数组
this.pendStates = []; // 待处理数组, state
this.isPending = false; // 更新频率控制,是否进行更新操作
}
// 添加回调队列
addCallback(callback) {
// 如果是函数,就将函数推到回调函数队列中,等待执行
if (_.isFn(callback)) {
this.pendingCallback.push(callback);
}
}
// 添加要更新的state队列
addState(nextState) {
if (nexState) {
this.pendStates.push(nexState);
// 进行此次更新
if (!this.isPending) {
this.emitUpdate();
}
}
}
// 更新
emitUpdate(nextProps, nextContext) {
// 调用getState函数
this.getState();
this.shouldUpdate();
}
// 获取更新之后的state
getState() {
let { instance, pendStates} = this;
let { state, props } = instance;
// 循环这次待更新的数据队列
this.pendStates.forEach(item => {
// 判断item是不是数组
let replace = _.isArr(nextState);
// 1.1如果是数组就对原数据进行替换
if (replace) {state = {...nextState};}
// 1.2如果是普通数据就对原数据进行解构更新操作
else {state = { ...state, ...nextState};}
})
return state;
}
shouldUpdate(component,nextProps,nextState,nextContext,callback) {
// 默认值是true
let shouldComponentUpdate = true;
if(component.shouldComponentUpdate) {
shouldComponentUpdate = component.shouldComponentUpdate(nextProps,nextState,nextContext);
}
// 判断shouldComponentUpdate,看看是否需要更新页面
// 不更新页面,赋值之后直接return
if(shouldComponentUpdate===false) {
component.props = nextProps;
component.state = nextState;
component.Context = nextContext || {};
return;
}
// 更新页面
let cache = component.$cache;
cache.props = nextProps;
cache.state = nextState;
cache.Context = nextContext || {};
component.forceUpdate(callback);
}
forceUpdate(callback) {
// 对之前页面dom的node和vnode进行赋值;
// 设置this.isPending = true;周期关闭
// 调用componentWillUpdate
// 对新的数据调用renderComponent方法生成新的vnode
// 调用compareTwoVnode进行新旧vnode的diff对比
}
}