整理向,非原創,目的是整理出淺顯易懂的方向性說明.
比如現有
this.state={name:"小明",age:18}
我們說修改組件的狀態要用this.setState()來實現.這里有兩個問題
1.為什么?我直接用this.state.age=17能不能實現重新渲染?
不能.因為它只是改變了這個組件當前的狀態,並沒有調用render().
2.this.setState()的原理是什么?
react中有一個原則:有變化,就一定返回一個新對象;沒變化,原對象不做變化直接返回;
結合這個原則我們來分析一下原理:
參數:
this.setState()有三個參數:分別是this.state、nextState和callback.
其中,第一個參數是默認已經給的,為什么還要提出來是為了方便理解.
第二個參數是新狀態,也就是我們期望組件能達到的狀態.有多種方式.傳一個對象或者傳一個返回對象的函數.最終效果就是傳一個對象.
this.setState({age:17})
第三個參數是設置成功之后的回調函數.
返回值:
this.setState()的返回值是一個新的對象,也就是說是一個新的狀態.它使用了Object.assign(),將已修改的屬性添加進去.而不是覆蓋.
this.state里面有兩個屬性,如果我 this.setState({age:17}) 這么操作會不會導致this.state里面沒有了"name"屬性?
不會!我們上面剛說,this.setState()是返回一個新的對象,它會把有變動的改變成變動后的值,沒有變動的保留.所以,你完全可以用這個方法去改變其中的某一個值.
接下來我們重點分析內部的原理:
首先,需要根據原來的this.state和傳進來的參數來判斷是否批量更改(是否批量差了一個收集待改組件的步驟),而這里的this.state是我之前說的默認傳進來的.
然后,再根據this.state來計算nextstate. (shouldComponentUpdate()根據拿到的nextstate來返回一個布爾值,true則進行下一步,false,則下一步不執行.然后就進入componentWillUpdate)
接着render()出一個next組件,
最后根據diff算法進行更新渲染. 結束后進入生命周期函數componentDidUpdate()
這里也有幾個問題:
(1)假如我調用this.setState()設置的值跟之前一樣的,會不會重新渲染一次?
會!因為shouldComponentUpdate()默認肯定返回true,所以一定會往下執行.那為什么我要是根據nextstate返回一個布爾值呢?因為我們可以手動通過這種方式來控制render()來減少無用功,這是shouldComponentUpdate()的功能,只不過沒有默認執行而已.
(2)假如我進行多次this.setState()的操作,而且都是同一個屬性修改最終以哪次為主?
function stateChange() { this.setState({age: this.state.age + 1}); this.setState({age: this.state.age + 1}); this.setState({age: this.state.age + 1}); }
這里情況比較復雜,大體上可以理解為在react的體制內setState()是異步操作,所以最后this.state.age最終還是只加了1,比如onClick()這種react原生的事件中.但是體制外的是同步操作.最終會加3.
(3)為啥console.log()拿不到最新的this.state?
如第(2)點所說,setState()是異步操作.還記得上面所說this.setState()還有一個參數是回調函數嗎?所以需要在this.setState()的參數里面再傳一個回調函數,在函數中打印就能得到this.state.