一.setState()的说明
1.更新数据
setState()是异步更新数据的
注意:使用该语法时,后面的setState()不要依赖于前面的setState)
可以多次调用setState(),只会触发一次重新渲染
2.推荐语法
推荐:使用setState((state, props)=>{})语法
参数state:表示最新的state
参数props:表示最新的props
3.第二个参数
场景:在状态更新(页面完成重新渲染)后立即执行某个操作
语法: setState(updater[, callback])
二.JSX语法的转化过程
JSX仅仅是createElement()方法的语法糖(简化语法)
JSX语法被@babel/preset-react插件编译为createElement()方法
React元素:是一个对象,用来描述你希望在屏幕上看到的内容
三.组件更新机制
setState()的两个作用:1.修改state 2.更新组件(UI)
过程∶父组件重新渲染时也会重新渲染子组件。但只会渲染当前组件子树(当前组件及其所有子组件)
四.组件性能优化
1.减轻state
减轻state :只存储跟组件渲染相关的数据(比如: count/列表数据/loading等)
注意:不用做渲染的数据不要放在state 中,比如定时器id等
对于这种需要在多个方法中用到的数据,应该放在this中
2.避免不必要的重新渲染
组件更新机制:父组件更新会引起子组件也被更新,这种思路很清晰
问题:子组件没有任何变化时也会重新渲染
如何避免不必要的重新渲染呢?
解决方式:使用钩子函数 shouldComponentUpdate(nextProps, nextState)
作用:通过返回值决定该组件是否重新渲染,返回true表示重新渲染,false表示不重新渲染
触发时机:更新阶段的钩子函数,组件重新渲染前执行( shouldComponentUpdate →render )
3.纯组件
纯组件:PureComponent与React.Component 功能相似
区别:PureComponent内部自动实现了shouldComponentUpdate钩子,不需要手动比较原理︰纯组件内部通过分别对比前后两次props和state的值,来决定是否重新渲染组件
说明︰纯组件内部的对比是 shallow compare(浅层对比)
对于引用类型来说∶只比较对象的引用(地址)赠否相同
注意:state或props 中属性值为引用类型时,应该创建新数据,不要直接修改原数据!(示例)
五.虚拟DOM和Diff算法
React 更新视图的思想是:只要state变化就重新渲染视图
特点:思路非常清晰
问题︰组件中只有一个DOM元素需要更新时,也得把整个组件的内容重新渲染到页面中?不是
理想状态:部分更新,只更新变化的地方。
问题:React是如何做到部分更新的?虚拟DOM配合Diff 算法
1.虚拟DOM
虚拟DOM:本质上就是一个JS对象,用来描述你希望在屏幕上看到的内容(UI )
2.执行过程
1.初次渲染时,React会根据初始state ( Model ),创建一个虚拟DOM对象(树)。
2.根据虚拟DOM生成真正的DOM,渲染到页面中。
3.当数据变化后( setState()),重新根据新的数据,创建新的虚拟DOM对象(树)。
4.与上一次得到的虚拟DOM对象,使用Diff算法对比(找不同),得到需要更新的内容。
5.最终,React 只将变化的内容更新( patch )到DOM中,重新渲染到页面。
3.代码演示
组件render()调用后,根据状态和JSX结构生成虚拟DOM对象
示例中,只更新p元素的文本节点内容
六.React原理揭秘
1.工作角度∶应用第一,原理第二。
2原理有助于更好地理解React的自身运行机制。
3. setState()异步更新数据。
4.父组件更新导致子组件更新,纯组件提升性能。
5.思路清晰简单为前提,虚拟 DOM和 Diff 保效率。
6.虚拟 DOM ->state + JSx。
7.虚拟DOM的真正价值从来都不是性能。