乐趣区

关于javascript:邂逅react十三-不可变数据的力量

react 中 state 的数据不可变准则, 为什么这么设计呢?
因为 react 的生命周期中每次调用 ComponentShouldUpdate()会将 state 现有的数据跟将要扭转的数据进行比拟, 更新发生变化的数据,最大限度缩小不必要的更新,达到性能的优化。所以不倡议间接更改 state 外面的数据,而是通过 setState 去扭转
对于 state 中间接扭转援用类型数据, 视图无奈更新的问题
小案例 1

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 里的援用数据类型基本不会触发视图更新的起因就是它~~~~

退出移动版