邂逅react(十三) 不可變數據的力量

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)
    }
 
}

如圖
image.png數組

再看另外一個場景:函數

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渲染頁面
       }) 
    }
}

效果圖
image.png
下面是圖解
image.png
圖解小結:
對lists進行push數據雖然發生了改變,可是其內存中存儲的url不會發生改變,因此不會觸發render對視圖進行更新
淺拷貝後的newArr1和lists數據是徹底同樣的,可是內存地址變了,因此會觸發視圖更新,咱們操做newArr後將它賦值給list,在componentShouldUpdate()週期的時候會比對新舊url,當檢測到url變化時會調用render函數,從新渲染咱們的視圖
看到這裏咱們就明白啦,直接改state裏的引用數據類型根本不會觸發視圖更新的緣由就是它~~~~性能

相關文章
相關標籤/搜索