首先引用個例子react
class Example extends React.Component {
constructor() {
super();
this.state = {
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val);
this.setState({val: this.state.val + 1});
console.log(this.state.val);
setTimeout(() => {
this.setState({val: this.state.val + 1});
console.log(this.state.val);
this.setState({val: this.state.val + 1});
console.log(this.state.val);
}, 0);
}
render() {
return null;
}
};
複製代碼
以上代碼依次輸出結果是?不知道的結果的能夠接下來看 知道結果的能夠直接跳過 結果依次是0 0 2 3 下面剖析下setState應用場景git
......
state = { val: 0 }
componentDidMount() {
this.setState({
val: this.state.val + 1
})
console.log(this.state.val)
}
......
複製代碼
這裏的輸出值仍是初始值0 看下源碼 關於github
function enqueueUpdate(component) {
......
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
......
}
複製代碼
看到有個if判斷 isBatchchingUpdates true & false 自行打個斷點能夠看到這componentDidMount時候已經將isBatchingUpdates設置了爲true 全部就會執行dirtyComponents.push(component); 不會立馬更新state 這時候打印就仍是初始值 0promise
這個if判斷的過程看似成了一個異步的操做bash
......
state = { val: 0 }
componentDidMount() {
setTimeout( () => {
this.setState({
val: this.state.val + 1
})
console.log(this.state.val)
})
}
......
複製代碼
這裏打印的是1 斷點看到這時候沒有batchedUpdate調用 isBatchingUpdates仍是爲false 這樣batchingStrategy.batchedUpdates(enqueueUpdate, component); 這就話就當即生效了 全部這時候val 會當即更新 打印是1異步
......
state = { val: 0 }
componentDidMount() {
this.setState({ val: this.state.val + 1 })
this.setState({ val: this.state.val + 1 })
this.setState({ val: this.state.val + 1 })
}
......
複製代碼
這裏結果仍是最後一個1 有一個update隊列 對最後一個更新async
var stateQueue = [] // state隊列
function mysetState(state, componentstate) {
// 寫一個異步的操做
if ( stateQueue.length === 0 ) {
promiseasync( cleanflush ); // 清空隊列
}
stateQueue.push({
state,
componentstate
})
}
function cleanflush() {
var item =setStateQueue.shift()
while(item) {
const { state, componentstate } = item
// 設置一個preState 保存以前的
if(!componentstate.prevState) {
componentstate.prevState = Object.assign( {}, componentstate.state);
}
if(typeof state === 'function') { // 判斷是否爲回調
Object.assign( componentstate.state, state( componentstate.prevState, componentstate.props ));
} else {
Object.assign(componentstate.state, state) // 合併state
}
}
}
function promiseasync(fn) {
return Promise.resolve().then(function() {
fn
})
}
複製代碼