react学习—PureComponent纯组件

一、PureComponent纯组件

纯组件用于避免不必要的渲染(render函数),提高效率

1、任务列表

//Task.js
import React, { Component } from 'react'
import PropTypes from "prop-types"
import './Task.css'

export default class Task extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    isFinish: PropTypes.bool.isRequired
  }
  render() {
    return (
      <li className={this.props.isFinish?"finish":""}>{this.props.name}</li>
    )
  }
}
//TaskList.js
import React, { Component } from 'react'
import PropTypes from "prop-types"
import Task from "./Task"

export default class TaskList extends Component {
  static propTypes = {
    tasks: PropTypes.arrayOf(PropTypes.shape({
      name: PropTypes.string.isRequired,
      isFinish
      : PropTypes.bool.isRequired
    })).isRequired
  }
  render() {
    const ts = this.props.tasks.map((it,i)=><Task
      key={i}
      {...it}
    />)
    return (
      <div>
        {ts}
      </div>
    )
  }
}

//TaskContainer.js
import React, { Component } from 'react'
import TaskList from "./TaskList"

export default class TaskContainer extends Component {
  state = {
    tasks: []
  }
  componentDidMount() {
    const ts = [];
    for(let i = 1;i <= 10;i ++){
      ts.push({
        name: `任务${i}`,
        isFinish: Math.random()>0.5
      })
    }
    this.setState({
      tasks: ts
    })
  }
  render() {
    return (
      <div>
        <TaskList tasks={this.state.tasks} />
      </div>
    )
  }
}

在这里插入图片描述
这是一个任务列表组件,TaskContainer开始渲染时组件没有任务数据,所以TaskList渲染时没有得到任务列表;当时TaskContainer得到10个任务数据后,setState触发该组件重新渲染,TaskList也就重新渲染并有了任务列表,所以Task组件就渲染了10次,此时并没有发现什么问题。
在这里插入图片描述

2、添加任务

此时我们增加一个添加任务的组件

//AddTask.js
import React, { Component } from 'react'

export default class AddTask extends Component {
  state = {
    name: ''
  }
  render() {
    return (
      <div>
        <input type="text" value={this.state.name}
          onChange={e=>{
            this.setState({
              name: e.target.value
            })
          }}
        />
        <button onClick={()=>{
          this.props.onAdd && this.props.onAdd({
            name: this.state.name,
            isFinish: false
          })
          this.setState({
            name: ''
          })
        }}>添加任务</button>
      </div>
    )
  }
}

//TaskContainer.js
import React, { Component } from 'react'
import TaskList from "./TaskList"
import AddTask from "./AddTask"

export default class TaskContainer extends Component {
  state = {
    tasks: []
  }
  componentDidMount() {
    const ts = [];
    for(let i = 1;i <= 10;i ++){
      ts.push({
        name: `任务${i}`,
        isFinish: Math.random()>0.5
      })
    }
    this.setState({
      tasks: ts
    })
  }
  render() {
    console.log('TaskContainer.js',this.state.tasks.length);
    return (
      <div>
        <AddTask
          onAdd={newTask=>{
            this.setState({
              tasks:[...this.state.tasks,newTask]
            })
          }}
        />
        <TaskList tasks={this.state.tasks} />
      </div>
    )
  }
}

在这里插入图片描述
此时我们发现TaskContainer组件前后得到数据后,AddTask组件也会重新渲染,这是不必要的。

接着清空控制台,并添加一条新的任务。
在这里插入图片描述
发现我们仅增加了一条新的任务,但是前面的10条任务同样重新渲染了,这会影响浏览器的渲染效率。

3、性能优化

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

//Task.js
import React, { Component } from 'react'
import PropTypes from "prop-types"
import './Task.css'

export default class Task extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    isFinish: PropTypes.bool.isRequired
  }
  export function ObjectEqual(obj1,obj2){
    for(let prop in obj1){
      if(!Object.is(obj1[prop],obj2[prop])){
        return false;
      }
    }
    return true;
  }
  shouldComponentUpdate(nextProps,newState){
    console.log("Task是否重新渲染");
    if(ObjectEqual(this.props,nextProps) && ObjectEqual(this.state,newState)){
      return false
    }
    return true;
  }
  render() {
    console.log("Task.js")
    return (
      <li className={this.props.isFinish?"finish":""}>{this.props.name}</li>
    )
  }
}

在这里插入图片描述
PureComponent是一个组件,如果一个组件继承自PureComponent,该组件的shouldComponentUpdate会自动优化,对属性和状态进行浅比较,没有变化则不进行渲染。

1.使用PureComponent

只要将继承的父组件改成PureComponent即可

//Task.js
import React, { PureComponent } from 'react'
import PropTypes from "prop-types"
import './Task.css'
import {ObjectEqual} from "../utils/helper"

export default class Task extends PureComponent {
  static propTypes = {
    name: PropTypes.string.isRequired,
    isFinish: PropTypes.bool.isRequired
  }
  shouldComponentUpdate(nextProps,newState){
    console.log("Task是否重新渲染");
    if(ObjectEqual(this.props,nextProps) && ObjectEqual(this.state,newState)){
      return false
    }
    return true;
  }
  render() {
    console.log("Task.js")
    return (
      <li className={this.props.isFinish?"finish":""}>{this.props.name}</li>
    )
  }
}

注意:PureComponent 是进行的浅比较

  1. 为了效率,尽量使用PureComponent
  2. 要求不要改动之前的状态,永远都是创建新的状态进行赋值
  3. 有一个三方库,Immutable.js,制作不可变对象
    函数组件使用React.memo制作纯组件
//Task.js
export default function Task(props) {
  console.log("Task.js")
  return (
    <div>
      <li className={props.isFinish?"finish":""}>{props.name}</li>
    </div>
  )
}
Task.propTypes = {
  name: PropTypes.string.isRequired,
  isFinish: PropTypes.bool.isRequired
}
React.memo(Task);

博主开始运营自己的公众号啦,感兴趣的可以关注“飞羽逐星”微信公众号哦,拿起手机就能阅读感兴趣的博客啦!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞羽逐星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值