阅读 67

React性能优化(二):将可变部分与不变部分分离

前言

大家好,我是疯狂的小波。在上一节# 一文看懂React优化原理及方案中,我们介绍了为什么要做性能优化,React的更新渲染机制,以及根据这个机制找到的3个性能优化方案。

这一节,我们就来看看第一种优化方案:将可变部分与不变部分分离

先简单来说下,什么是可变部分

React 中,只要组件的state数据有变更,当前组件就会重新渲染。state数据有3个组成部分:propsstatecontext只要这几个数据会产生变更,我们就称使用这部分数据的内容为可变部分

propscontext 是基于 state 的扩展,其实就是父级、祖先级组件传递过来的 state

那应该怎么进行分离呢?可以将数据会变动的内容单独拆分到一个组件中,这样就不会影响到父节点和其他的同级节点。

一个简单的例子

如,下面代码中:每次点击p标签更改 count 值时,AppChildren 组件都会重新渲染一次,即使此时 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 时,AppChildren 组件也不会重新渲染了。这样就达到了我们的目的,只更新数据变更的内容

我们可以看到,进行可变数据分离的目的,就是将变更的那一部分数据拆分到独立的组件中,这样父组件数据就不会变更,父组件完成了性能优化,不会重新渲染,其他子组件 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 组件,AppChildren 组件不会重新渲染。

这种方式可能并不是那么好理解,并且在结构更复杂时,不一定适用。

无法分离时

有时父组件的数据可能会有很多,并且可能会将props传递给多个子组件,此时就很难将所有的数据变更都拆分到子组件中了。这种情况下,父组件必然就会产生数据变更,导致重新渲染,其子组件也会全部重新渲染。

这种情况下上面的这种优化策略就无法满足我们了,但是我们可以使用前面提到的第二种优化方案 :使用性能优化API,进行处理。也就是我们下一章节的内容


作者:疯狂的小波
链接:https://juejin.cn/post/7169773969115971598


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐