zoukankan      html  css  js  c++  java
  • PureComponent的作用及一些使用陷阱

    默认渲染行为的问题

    在React Component的生命周期中,有一个shouldComponentUpdate方法。这个方法默认返回值是true。

    这意味着就算没有改变组件的props或者state,也会导致组件的重绘。这就经常导致组件因为不相关数据的改变导致重绘,这极大的降低了React的渲染效率。比如下面的例子中,任何options的变化,甚至是其他数据的变化都可能导致所有cell的重绘。

    //Table Component
    {this.props.items.map(i =>
        <Cell data={i} option={this.props.options[i]} />
    )}
    

    重写shouldComponentUpdate

    为了避免这个问题,我们可以在Cell中重写shouldComponentUpdate方法,只在option发生改变时进行重绘。

    class Cell extends React.Component {
      shouldComponentUpdate(nextProps, nextState) {
        if (this.props.option === nextProps.option) {
          return false;
        } else {
          return true;
        }
      }
    }
    

    这样每个Cell只有在关联option发生变化时进行重绘。

    使用PureComponent与immutable.js

    因为上面的情况十分通用,React创建了PureComponent组件创建了默认的shouldComponentUpdate行为。这个默认的shouldComponentUpdate行为会一一比较props和state中所有的属性,只有当其中任意一项发生改变是,才会进行重绘。

    需要注意的是,PureComponent使用浅比较判断组件是否需要重绘

    因此,下面对数据的修改并不会导致重绘(假设Table也是PureComponent)

      options.push(new Option())
      options.splice(0, 1)
      options[i].name = "Hello"
    

    这些例子都是在原对象上进行修改,由于浅比较是比较指针的异同,所以会认为不需要进行重绘。

    为了避免出现这些问题,推荐使用immutable.js。immutable.js会在每次对原对象进行添加,删除,修改使返回新的对象实例。任何对数据的修改都会导致数据指针的变化。

    其他的陷阱

    需要注意的是,还有一些小陷阱需要避免。

    1. Literal Array与Literal Object
    {this.props.items.map(i =>
        <Cell data={i} options={this.props.options || []} />
    )}
    

    若options为空,则会使用[]。[]每次会生成新的Array,因此导致Cell每次的props都不一样,导致需要重绘。解决方法如下:

    const default = [];
    {this.props.items.map(i =>
      <Cell data={i} options={this.props.options || default} />
    )}
    
    1. 内联函数
      函数也经常作为props传递,由于每次需要为内联函数创建一个新的实例,所以每次function都会指向不同的内存地址。比如:
    render() {
         <MyInput onChange={e => this.props.update(e.target.value)} />;
    }
    

    以及:

    update(e) {
         this.props.update(e.target.value);
    }
    render() {
         return <MyInput onChange={this.update.bind(this)} />;
    }
    

    注意第二个例子也会导致创建新的函数实例。为了解决这个问题,需要提前绑定this指针:

    constructor(props) {
        super(props);
        this.update = this.update.bind(this);
      }
      update(e) {
        this.props.update(e.target.value);
      }
      render() {
        return <MyInput onChange={this.update} />;
      }
    


    作者:橙子_80c3
    链接:https://www.jianshu.com/p/33cda0dc316a
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
     
    ===================
    所以根据上述描述,以前在react中,使用箭头函数,虽然方便了函数的编写,但是会造成每次render都会渲染的问题!所以要改成在constructor函数中对函数绑定this。
    注意的是,有些时候不可避免的要用到箭头函数或者在render中bind this 比如要传递参数时:
     
    <ul>
        {
        list.map((item,index) => {
            return (
            <li key={index} onClick={()=>{deleteList(index)} }>{item}</li>
            )
        })
        }
    </ul>

    注意上面,传递index时,箭头函数前面不要填写index,而在函数里面输入index。因为在函数前面的index相当于event了  onClick ={(index)=>{deleteList(index)}}  

    <ul>
        {
        list.map((item,index) => {
            return (
            <li key={index} onClick={deleteList.bind(this,index) }>{item}</li>
            )
        })
        }
    </ul>
     
     
     
  • 相关阅读:
    树的定义与存储
    软件测试概论二
    软件测试概论
    抽象数据类型
    java编程总结01---20190214
    java 按行读取本文文件并存放到mongodb中
    刷题感悟
    刷题感悟- Binary Tree Path Sum
    java io与nio
    java IO 学习笔记
  • 原文地址:https://www.cnblogs.com/xiaozhumaopao/p/10545923.html
Copyright © 2011-2022 走看看