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 是进行的浅比较
- 为了效率,尽量使用PureComponent
- 要求不要改动之前的状态,永远都是创建新的状态进行赋值
- 有一个三方库,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);
博主开始运营自己的公众号啦,感兴趣的可以关注“飞羽逐星”微信公众号哦,拿起手机就能阅读感兴趣的博客啦!