邂逅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里的引用数据类型根本不会触发视图更新的缘由就是它~~~~性能

相关文章
相关标签/搜索