用于避免重复渲染(执行render函数),提高效率
以下面的示例:
// 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执行了多少次,
优化:如果一个组件的属性和状态都没有发生变化,重新渲染组件是没有必要的
简单优化,以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}/>
}
}
}
*/