react是个运行时runtime框架,每次的更新都会从根节点进行全方位的编辑,生成全新的fiber树,而不像vue那样有自己的编译语法只会diff发生update的组件,所以react性能上存在优化的空间,那么怎样做才会减少组件的render呢。。。
- 组件的render需要状态的变化:
- props
- state
- context
避免组件的重复渲染,就是避免不需要渲染的组件中有以上状态的变化
重点就是将变的组件和不变的组件抽离开
// 一个不好的示例
// 以下代码只要触发input就会同时导致sleep render,造成性能的浪费
function App(){
const [num, updateNum]=useState(0);
return (
<div>
<input value = {num} onChange=>{e=>updateNum(e.target.value)}>
<Sleep/>
</div>
)
}
function Sleep(){ //阻塞函数
let now = performance.now();
while(performance.now()-now<100){}// 阻塞逻辑
console.log(`耗时组件render`)
return <p>耗时组件</p>
}
// 正确应该是这样进行处理
// 只涉及到了Count的render不会导致没有变化的Sleep的重复渲染,命中性能优化
function App(){
return (
<div>
<Count/>
<Sleep/>
</div>
)
}
function Count(){
const [num, updateNum]=useState(0);
return (
<input value = {num} onChange=>{e=>updateNum(e.target.value)}>
)
}
//-------------------------------------------
// 如果是这样的
function App(){
const [num, updateNum]=useState(0);
return (
<div title={num}>
<input value = {num} onChange=>{e=>updateNum(e.target.value)}>
<Sleep/>
</div>
)
}
// 可以这样处理
function App(){
return (
<Out>
<Sleep/>
</Out>
)
}
function Out(children){// 把关于num的状态全部都抽离出来
const [num, updateNum]=useState(0);
return (
<div title={num}>
<input value = {num} onChange=>{e=>updateNum(e.target.value)}>
{children}
</div>
)
}
以上示例说明了
当父组件满足性能优化条件子孙组件可能命中性能优化
换句话说
子组件所在的父组件(直至根组件)中没有props、 state、 context变化的话,子组件如果也不需要更新状态,这个子组件可以避免重复render(命中性能优化)
react自带的优化方法PureComponent、 usememo 、 usecallback等
当我们的组件树从某个节点开始不能命中性能优化后,即使子组件做了变与不变的抽离,不变的子组件仍然会触发render(不会命中性能优化)
因为props默认的值是一个空对象{},react的更新会用全等比较新旧props。oldProps===newProps 肯定是false,所以会导致更新。
所以usememo \ usecallback就可以派上用场了,他们采用的是比对方式是对象的浅比较,只要props里的属性值没有变化的话都不会触发render(性能会比较差<因为浅比较,所以不要滥用>,但是会更容易触发性能优化)
网友评论