22-PureComponent性能优化和功能实现

70 阅读2分钟

PureComponent

  • 看一下下面的例子对比
  • 这种写法不会造成视图的更新,但是render方法却执行了这就浪费性能了
    • 正常人不会这么写的
  • 为什么会出现这种问题尼?
    • 继承Component,当修改的值的地址没有改变时候,react会被判定值没有改变,所以视图不进行更新
import React, { Component } from 'react'

export default class PureComp extends Component {
  state = {
    arr: [10, 20]
  }
  handler = () => {
    let { arr } = this.state;// arr -> 0x0001
    arr.push(30);
    // 改状态值,并不会让视图更新
    this.setState({
      arr// => arr -> 0x0001 此时0x001中新增30
    })
  }
  render() {
    let { arr } = this.state;
    console.log(arr, 'render');
    return (
      <div>
        { arr }
        <br />
        <button onClick={ this.handler }>处理</button>
      </div>
    )
  }
}

image.png

  • 继承PureComponent
    • 继承React.PureComponent,会默认创建一个 shouldComponentUpdate
    • 在这个生命周期中做了一个浅比较
      • 拿最新修改的值和状态,和之前的属性状态进行比较,如果一样则不去更新
import React, { PureComponent } from 'react'

export default class PureComp extends PureComponent {
  state = {
    arr: [10, 20]
  }
  handler = () => {
    let { arr } = this.state;// arr -> 0x0001
    arr.push(30);
    // 改状态值,并不会让视图更新
    this.setState({
      arr// => arr -> 0x0001 此时0x001中新增30
    })
  }
  render() {
    let { arr } = this.state;
    console.log(arr, 'render');
    return (
      <div>
        { arr }
        <br />
        <button onClick={ this.handler }>处理</button>
      </div>
    )
  }
}

image.png

继承 Component这个类去简单模拟 PureComponent这个类

  • 达到上面PureComponent的效果
import React, { Component, PureComponent } from 'react'

// 是否是对象
function isObject(obj) {
  if(typeof obj === 'object' && obj !== null) return true;
}
// 浅比较
function compare(obj1, obj2) {
  // 内存是否相等
  if(obj1 === obj2) return true;
  // 其中有一个不是对象 就不相等
  if(!isObject(obj1) && !isObject(obj2)) return false;
  // 键值对数量是否一致
  let keys1 = Reflect.ownKeys(obj1),
      keys2 = Reflect.ownKeys(obj2);
  if(keys1.length !== keys2.length) return false;
  // 是对象且堆内存地址不同: 值是否相等
  return keys1.every(key => {
    // 如果属性是个对象的话 递归不过这边是浅比较我们就比较第一层就行了
    // if(isObject(obj1[key]) && isObject(obj2[key])) {
    //   return compare(obj1[key], obj2[key]);
    // }
    // 不是对象类型的相等就
    return obj1[key] === obj2[key];
  })
}
export default class PureComp extends Component {
  state = {
    arr: [10, 20]
  }
  handler = () => {
    let { arr } = this.state;// arr -> 0x0001
    arr.push(30);
    // 改状态值,并不会让视图更新
    this.setState({
      arr// => arr -> 0x0001 此时0x001中新增30
    })
  }
  shouldComponentUpdate(nextProps, nextState) {
    return !compare(this.props, nextProps) || !compare(this.state, nextState);
  }
  render() {
    let { arr } = this.state;
    console.log(arr, 'render');
    return (
      <div>
        { arr }
        <br />
        <button onClick={ this.handler }>处理</button>
      </div>
    )
  }
}

image.png

总结

  • PureComponent可以做性能的优化
  • this.setState设置值的时候,不要再原来的地址上操作 or this.forceUpdate()跳过shouldComponentUpdate(不推荐使用)
  • 项目中直接使用 PureComponent就行了,如非必要不要去搞事情