React 之 PureComponent

用于避免重复渲染(执行render函数),提高效率

以下面的示例:

pure1

// taskContainer 组件
class TaskContainer extends Component {
  state = {
    taskList: []
  };

  componentDidMount() {
    const task = [];
    for (let i = 0; i < 10; i++) {
      task.push({
        isFinish: Math.random() > 0.5,
        name: `任务${i}`
      });
    }

    this.setState({
      taskList: task
    });
  }

handleAdd = val =>{
    this.setState({
              taskList: [...this.state.taskList, val]
            });
}

  render() {
    console.log("container render");
    return (
      <div>
        <TaskList task={this.state.taskList} />
        <AddTask
          add={this.handleAdd}
        />
      </div>
    );
  }
}

// TaksList
class TaskList extends Component {
  static propTypes = {
    task: PropTypes.arrayOf(
      PropTypes.shape({
        isFinish: PropTypes.bool,
        name: PropTypes.string
      })
    )
  };

  render() {
    console.log("taskList render");
    return (
      <ul>
        {this.props.task.map(el => (
          <Task {...el} />
        ))}
      </ul>
    );
  }
}

// Task
class Task extends Component {
  static propTypes = {
    isFinish: PropTypes.bool,
    name: PropTypes.string
  };
  render() {
    console.log("task render");
    return (
      <li className={this.props.isFinish ? "isfinish" : ""}>
        {this.props.name}
      </li>
    );
  }
}

//AddTask
class AddTask extends Component {
  state = {
    name: ""
  };

  render() {
    console.log("addTask render");
    return (
      <div>
        <input
          type="text"
          value={this.state.name}
          onChange={e => {
            this.setState({
              name: e.target.value
            });
          }}
        />
        <button
          onClick={() => {
            this.props.add({
              isFinish: false,
              name: this.state.name
            });
          }}
        >
          添加任务
        </button>
      </div>
    );
  }
}

来看下,每个组件render执行了多少次,

pure2

优化:如果一个组件的属性和状态都没有发生变化,重新渲染组件是没有必要的

简单优化,以addTask组件为例:

采用shouldComponentUpdate来进行优化

import React, { Component } from "react";

export default class AddTask extends Component {
  state = {
    name: ""
  };

  objectEqual(cure, next) {
    for (let i in cure) {
      if (!Object.is(cure[i], next[i])) {
        return false;
      }
    }
    return true;
  }

// 优化部分 
/*
* 将当前props和nextProps 当前state和nextState 两者进行浅比较
* 两者都没有发生改变 则不重新渲染 反之重新渲染啊
*/
  shouldComponentUpdate(nextProps, nextState) {
    if (
      this.objectEqual(this.props, nextProps) &&
      this.objectEqual(this.state, nextState)
    ) {
      return false;
    }
    return true;
  }

  render() {
    console.log("addTask render");
    return (
      <div>
        <input
          type="text"
          value={this.state.name}
          onChange={e => {
            this.setState({
              name: e.target.value
            });
          }}
        />
        <button
          onClick={() => {
            this.props.add({
              isFinish: false,
              name: this.state.name
            });
          }}
        >
          添加任务
        </button>
      </div>
    );
  }
}

采用PureComponent来进行优化

import React, { PureComponent } from "react";

// 将Component ->  PureComponent
export default class AddTask extends PureComponent {
  state = {
    name: ""
  };

  render() {
    console.log("addTask render");
    return (
      <div>
        <input
          type="text"
          value={this.state.name}
          onChange={e => {
            this.setState({
              name: e.target.value
            });
          }}
        />
        <button
          onClick={() => {
            this.props.add({
              isFinish: false,
              name: this.state.name
            });
          }}
        >
          添加任务
        </button>
      </div>
    );
  }
}

PureComponent是一个组建,如果某一个组件继承自该组件,则该组件的shouldComponentUpdate会进行优化,对属性和状态进行浅比较,对属性和状态惊醒浅比较,如果相等则不会重新渲染

其他组件的改写我就不再演示…

注意

进行的是浅比较

1.为了效率,应该尽量使用PureComponent

​ 1.要求不要改动之前的状态,永远是创建心得状态覆盖之前的状态(Immutable,不可变对象)

​ 2.有一个第三方js库,Immutable.js,专门用于制作不可变对象

2.函数组件,使用React.memo()制作纯组件

// 以task函数组件为例
function Task(props) {
  console.log("task render");
  return <li className={props.isFinish ? "isfinish" : ""}>{props.name}</li>;
}

Task.propTypes = {
  isFinish: PropTypes.bool,
  name: PropTypes.string
};

export default React.memo(Task);  // 这里的其实就是一个高阶组件
/*
function Memo(Comp){
    return class MemoWrap extends PureComponent {
        render(){
            return <Comp {...this.props}/>
        }
    }
}
*/
发布了45 篇原创文章 · 获赞 14 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/cmchenmei/article/details/104023471