react中 state的數據不可變原則,爲何這麼設計呢?
由於react的生命週期中每次調用ComponentShouldUpdate()會將state現有的數據跟將要改變的數據進行比較,更新發生變化的數據,最大限度減小沒必要要的更新,達到性能的優化。因此不建議直接更改state裏面的數據,而是經過setState去改變
關於state中直接改變引用類型數據,視圖沒法更新的問題
小案例1react
class TheState extends Component { constructor(props){ super(props) this.state={ lists:[ {name:'dabai',age:18}, {name:'xhh',age:20}, {name:'ali',age:25} ], num:0 } } render() { return ( <div> { this.state.lists.map((item,index)=>{ return( <ul key={item+index}> <li> {item.name}---{item.age} </li> </ul> ) }) } <button onClick={this.addListsData.bind(this)}>添加數據</button> </div> ); } addListsData(){ let data3={name:'xiaohui',age:22} this.state.lists.push(data3) //直接push原state裏面的lists不會引發視圖更新 console.log(this.state.lists) } }
如圖數組
再看另外一個場景:函數
class TheState extends Component { constructor(props){ super(props) this.state={ lists:[ {name:'dabai',age:18}, {name:'xhh',age:20}, {name:'ali',age:25} ] } } render() { return ( <div> { this.state.lists.map((item,index)=>{ return( <ul key={item+index}> <li> {item.name}---{item.age} <button onClick={this.addAge.bind(this,index)} style={{marginLeft:'20px'}}>增長年齡 </button> </li> </ul> ) }) } <button onClick={this.addListsData.bind(this)}>添加數據</button> </div> ); } addListsData(){ let data3={name:'xiaohui',age:22} let newArr1=[...this.state.lists]//淺拷貝一份數據 newArr1.push(data3) //往拷貝的數組裏push數據 console.log(newArr1) this.setState({ lists:newArr1 //將改變後的數據從新賦值給原有的對象 這時react內部會調用render刷新數據 }) //**** 注意 直接push原state裏面的lists不會引發視圖更新 稍後圖解 */ } addAge(index){ let newArr2=[...this.state.lists]//淺拷貝一份數據 newArr2[index].age+=1 //修改拷貝後的數據 this.setState({ lists:newArr2 //從新賦值 調用render渲染頁面 }) } }
效果圖
下面是圖解
圖解小結:
對lists進行push數據雖然發生了改變,可是其內存中存儲的url不會發生改變,因此不會觸發render對視圖進行更新
淺拷貝後的newArr1和lists數據是徹底同樣的,可是內存地址變了,因此會觸發視圖更新,咱們操做newArr後將它賦值給list,在componentShouldUpdate()週期的時候會比對新舊url,當檢測到url變化時會調用render函數,從新渲染咱們的視圖
看到這裏咱們就明白啦,直接改state裏的引用數據類型根本不會觸發視圖更新的緣由就是它~~~~性能