react 组件进阶之 pureComponent(纯组件)

简介: react 组件进阶之 pureComponent(纯组件)

阅读下面的代码,请回答 render 总共执行了多少次?这个问题涉及到react的生命周期。

代码如下


import React, { Component, PureComponent } from 'react'
/**
 * 组件有两个状态,一个是li,另一个是添加li
 */
interface ITestPureComponentS {
  lis: number[],
  addLi: (li: number) => void
}
// 测试li 组件
class TestLi extends Component {
  render() {
    console.log('TestLi render');
    return (
      <li>{this.props.children}</li>
    )
  }
}
export default class TestPureComponent extends Component<{}, ITestPureComponentS> {
  state = {
    lis: [],
    addLi: (li: number) => {
      this.setState({
        lis: [...this.state.lis, li]
      })
    }
  }
  // 组件即将渲染的时候,添加10个li
  componentDidMount() {
    let lis: number[] = []
    for (let i = 1; i <= 10; i++) {
      lis.push(i)
    }
    this.setState({
      lis: lis
    })
  }
  /**
   * 添加一个li
   */
  addLis = () => {
    const num = Date.now()
    this.state.addLi(num)
  }
  render() {
    console.log('TestPureComponent render');
    const lisD = this.state.lis.map(i => {
      return (
        <TestLi key={i}>{i}</TestLi>
      )
    })
    return (
      <div>
        {lisD}
        <button onClick={this.addLis}>添加一个li</button>
      </div>
    )
  }
}


20210313095708397.png


分析


  • app 组件: 这里只是直接挂载,没有做任何操作,所以render 只会执行一次
  • TestPureComponent组件: 组件挂载阶段, 是需要执行一次的,然后组件挂载完毕后,我们手动setState({}) ,调用这个方法是会触发组件的render()函数的。 然后它还要在执行一次,所以这个组件的render() 总共执行两次
  • TestLi组件: 在父组件被render的同时子组件也会调用render(), 我们这里是直接使用 this.state.lis 的,一开始是空的,里面是没有 TestLi 组件的. 所以该组件执行的次数 应该为 10 次


打印结果


20210313100744393.png


如果可以答对的网友,恭喜你,对react 的生命周期还是蛮清楚的。加油,继续往下


点击,添加一个li render 又会执行多少次?


分析


  • TestPureComponent 组件: 点击按钮会触发 this.setState() 所以,TestPureComponent 组件必然会执行 render() ,该组件会执行 render 1次
  • TestLi组件 由于父组件执行render 并且数据发生变化,里面的值多了一个,所以改组件会执行 11 次


效果


20210313104054377.png


注意: 我们只是加了一个数据,并且数据都没有变化,为啥要渲染11次呀,这个render 虽然只是一点点的性能,如果组件树大了,那么render的次数也会相应的变得庞大。这个是非常影响性能的。所以有没有啥优化方法?


优化方法一: 代码结构优化,我们不在render()这里 进行map遍历,而是直接在componentDidMount的时候直接生成一个TestLi组件的数组,然后改变数据就不会重新渲染了, 如果网友你能想到这个问题?那确实你react 方面掌握的是非常厉害的。本人是刚刚误打误撞发现的。但是在大部分同学写代码都不怎么能优化,所以选择优化方法二;


优化方法二:shouldComponentUpdate(nextProps, nextState) 这里面能够直接决定是否需要重新 执行 render, 所以优化的方法就在这个路口,优化的思路也是比较容易的,将传递过来的state 和 props 和当前的 state, props进行比较,如果变化了,那么直接return true, 否则 return false;


在TestLi组件中进行优化


// 测试li 组件
class TestLi extends Component {
  /**
   * 浅判断
   * @param obj 
   * @param obj2 
   * @returns 
   */
  objectIsEqual(obj: any, obj2: any) {
    for (const key in obj) {
      if (Object.is(obj[key], obj2[key])) {
        return true;
      }
    }
    return false
  }
  shouldComponentUpdate(nextProps: {}, nextState: {}) {
    if (this.objectIsEqual(nextProps, this.props)) {
      return false;
    }
    return true
  }
  render() {
    console.log('TestLi render');
    return (
      <li>{this.props.children}</li>
    )
  }
}


效果


20210313110723649.png


注意: 有的网友又要问了,为啥要使用浅比较 而不进行深比较,个人决定浅比较不怎么消耗内存,省时省力。如果深度比较的话,那么就会比较消耗内存了,并且我们是在做优化操作,不需要进行深度比较。


PureComponent


PureComponent 就是上面TaskLi 里面封装的一个组件,改组件继承component, 里面的实现思路也是一样的,都是在shouldComponentUpdate 这里进行操作的,也是使用的是浅比较

代码改写成这样,也是可以实现一样的效果


// 测试li 组件
class TestLi extends PureComponent {
  render() {
    console.log('TestLi render');
    return (
      <li>{this.props.children}</li>
    )
  }
}

20210313111224511.png


注意


1.pureComponent 是纯组件,进行的是浅比较,因此数据如果涉及到引用类型的,如对象或者数组等,需要重新创建一个,不然是无法进行数据更新的。为了效率,我们应该使用这个组件


2.要求不改变之前的状态,需要对状态进行覆盖(Immutable)这个公共库可以避免我们犯错,具体的请自行查看。


3.如果函数组件需要使用纯组件,需要使用 React.memo 制作村组件,这个memo就是一个高阶组件,里面返回的还是一个类组件。有兴趣的自己编写

相关文章
|
3月前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
40 0
|
2月前
|
前端开发 中间件 数据安全/隐私保护
React路由进阶方法
React路由进阶方法
25 1
|
2月前
|
存储 前端开发 中间件
React组件间的通信
React组件间的通信
16 1
|
2月前
|
前端开发 应用服务中间件 数据库
react服务端组件
react服务端组件
21 0
|
2月前
|
前端开发 JavaScript
快速上手React:从概述到组件与事件处理
快速上手React:从概述到组件与事件处理
|
3月前
|
前端开发 JavaScript API
React组件生命周期
React组件生命周期
74 1
|
3月前
|
资源调度 前端开发 JavaScript
React组件
React组件
41 0
|
3月前
|
存储 前端开发 JavaScript
探索 React Hooks 的世界:如何构建出色的组件(下)
探索 React Hooks 的世界:如何构建出色的组件(下)
探索 React Hooks 的世界:如何构建出色的组件(下)
|
6月前
|
前端开发
React-父子组件通讯
React-父子组件通讯
25 0
React-父子组件通讯
|
3月前
|
存储 前端开发 JavaScript
React组件中如何通讯
React组件中如何通讯
16 0