前端开发那些事儿

React PureComponent简介

2020-11-12  本文已影响0人  菜菜的小阿允
一、为什么使用?

React15.3中新加了一个 PureComponent 类,取代其前身 PureRenderMixin。顾名思义, pure 是纯的意思,PureComponent 即纯组件,PureComponent 是优化 React 应用程序最重要的方法之一,使用PureComponent可以减少不必要的 render 操作的次数,从而提高性能,而且可以少写 shouldComponentUpdate 函数,节省代码。

二、原理

当组件更新时,如果组件的 props 和 state 都没发生改变,render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动帮我们做了一层浅比较:

if (this._compositeType === CompositeTypes.PureClass) {
  shouldUpdate = !shallowEqual(prevProps, nextProps)
  || !shallowEqual(inst.state, nextState);
}

而 shallowEqual 又做了什么呢?会比较 Object.keys(state | props) 的长度是否一致,每一个 key是否两者都有,并且是否是一个引用,也就是只比较了第一层的值,确实很浅,所以深层的嵌套数据是对比不出来的。

三、原则

PureComponent的组件在props或者state的属性值是对象的情况下,并不能阻止不必要的渲染,是因为自动加载的shouldComponentUpdate里面做的只是浅比较,所以想要用PureComponent的特性,应该遵守原则:

四、用法

使用方式很简单:

import React { PureComponent, Component } from 'react';

class Foo extends (PureComponent || Component) {
  //...
}

一些要注意的地方:

handleClick() {
  let {items} = this.state

  items.push('new-item')
  this.setState({ items })
}

render() {
  return (
    <div>
      <button onClick={this.handleClick} />
      <ItemList items={this.state.items} />
    </div>
  )
}

由于ItemList是一个纯组件,这时候点击它是不会被渲染的,但是我们的确向this.state.items加入了新的值,但是它仍然指向同一个对象的引用。但是,通过移除可变对象就很容易改变这种情况,使之能够正确被渲染。

handleClick() {
  this.setState(prevState => ({
    words: prevState.items.concat(['new-item'])
  }))
}
class App extends PureComponent {
  state = {
    items: [{ name: 'test1' }, null, { name: 'test3'  }]
  }
  store = (id, value) => {
    const { items } = this.state;
    items[id]  = assign({}, items[id], { name: value });
    this.setState({ items: [].concat(items) });
  }
  render() {
    return (< div>
      < ul>
        {this.state.items.map((i, k) =>
          < Item store={this.store} key={k} id={k} data={i || {}} />)
        }
      < /ul>
    < /div>)
  }
}

当某一个子组件调用 store 函数改变了自己的那条属性,触发 render 操作,如果数据是 null 的话 data 属性每次都是一个 {},{} ==== {} 是 false 的,这样无端的让这几个子组件重新 render 了。最好设置一个 defaultValue 为 {},如下:

defaultValue = {}
< Item store={this.store} key={k} id={k} data={i || defaultValue} />
上一篇 下一篇

猜你喜欢

热点阅读