theme: orange
开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情。
前言
大家好,我是疯狂的小波。在上一节# 一文看懂React优化原理及方案中,我们介绍了为什么要做性能优化,React的更新渲染机制,以及根据这个机制找到的3个性能优化方案。
这一节,我们就来看看第一种优化方案:将可变部分与不变部分分离
先简单来说下,什么是可变部分
。
在 React
中,只要组件的state数据
有变更,当前组件就会重新渲染。state数据
有3个组成部分:props
、state
、context
,只要这几个数据会产生变更,我们就称使用这部分数据的内容为可变部分。
props
、context
是基于state
的扩展,其实就是父级、祖先级组件传递过来的state
那应该怎么进行分离呢?可以将数据会变动的内容单独拆分到一个组件中,这样就不会影响到父节点和其他的同级节点。
一个简单的例子
如,下面代码中:每次点击p
标签更改 count
值时,App
、Children
组件都会重新渲染一次,即使此时 Children
组件的数据并没有任何变动。如果 App
中还有其他的组件,也会重新渲染,显然这是不符合我们预期的,造成了性能浪费。
function App() {
const [count, setCount] = useState(0)
const add = () => {
setCount(count + 1)
}
return (
<div className="App">
<p onClick={add}>{count}</p>
<Children />
</div>
);
}
function Children() {
console.log("子组件渲染");
return <div>子组件</div>
}
这时,我们就可以将 可变的这一部分内容(count
),单独拆分到一个组件中,进行隔离。如下:
function App() {
return (
<div className="App">
<Count />
<Children />
</div>
);
}
function Count() {
const [count, setCount] = useState(0)
const add = () => {
setCount(count + 1)
}
return <p onClick={add}>{count}</p>
}
我们将 count
数据相关内容单独拆分到了 Count
组件中,此时再点击 p
标签变更 count
时,App
、Children
组件也不会重新渲染了。这样就达到了我们的目的,只更新数据变更的内容。
我们可以看到,进行可变数据分离的目的,就是将变更的那一部分数据拆分到独立的组件中,这样父组件数据就不会变更,父组件完成了性能优化,不会重新渲染,其他子组件 props
没有变更的也就不会重新渲染了。
这也就是为什么我们都非常提倡合理的进行组件拆分的原因。不光是更有利于项目的可维护性、可读性,合理的组件拆分同时也能提高项目的性能。
复杂一点的例子
还是基于上面的demo,如果此时 App
组件中,也有部分内容使用到了 count
,该怎么处理?
function App() {
const [count, setCount] = useState(0)
const add = () => {
setCount(count + 1)
}
return (
<div className="App" title={count}>
<p onClick={add}>{count}</p>
<Children />
</div>
);
}
如上,我们在 App
的根节点上,将 count
作为 title
使用,此时就不能简单的像刚刚那样,把这部分内容拆分成一个完全独立的组件了,因为内部还有 Children
组件。此时,也可以如下处理:
function App() {
return (
<CountWrapper>
<Children />
</CountWrapper>
);
}
function CountWrapper({children}) {
const [count, setCount] = useState(0)
const add = () => {
setCount(count + 1)
}
return (
<div className="App" title={count}>
<p onClick={add}>{count}</p>
{children}
</div>
)
}
还是将 count
的相关内容拆分到到组件 CountWrapper
中,然后通过组件的 props.children
属性渲染子组件。此时 count
数据变更,也只会重新渲染 CountWrapper
组件,App
、Children
组件不会重新渲染。
这种方式可能并不是那么好理解,并且在结构更复杂时,不一定适用。
无法分离时
有时父组件的数据可能会有很多,并且可能会将props
传递给多个子组件,此时就很难将所有的数据变更都拆分到子组件中了。这种情况下,父组件必然就会产生数据变更,导致重新渲染,其子组件也会全部重新渲染。
这种情况下上面的这种优化策略就无法满足我们了,但是我们可以使用前面提到的第二种优化方案 :使用性能优化API,进行处理。也就是我们下一章节的内容。
暂无评论内容