某些值没有达到改变的条件或者没有必要渲染,但用户点击了;整个组件仍然是重新渲染了的。显然,这一次渲染是没有必要的。
例子:
import React from 'react'
export default class App extends React.Component {
constructor() {
super();
this.state = {
counter: 1
}
}
render() {
console.log("App 渲染了");
return (
<div>
<h1>App 组件</h1>
<div>{this.state.counter}</div>
<button onClick={() => this.setState({
counter : 1
})}>+1</button>
</div>
)
}
}
方式一
使用shouldComponentUpdate来决定是否渲染
import React, { Component } from 'react'
import { objectEqual } from "../utils/tools"
export default class ClassOptimize extends Component {
constructor() {
super();
this.state = {
counter: 1
}
}
/**
*
* @param {*} nextProps 新的 props
* @param {*} nextState 新的 state
* @returns
*/
shouldComponentUpdate(nextProps, nextState) {
// shouldComponentUpdate会根据返回值来决定是否重新渲染
// 默认是 true,要重新渲染
// 如果返回 false,则不会重新渲染
// 我们就需要将当前的 props 和 state 与新的 props 和 state 进行一个比较
if (objectEqual(this.props, nextProps) && objectEqual(this.state, nextState)) {
// 如果新旧 props 和 state 都是相同的,那么就返回 false,不需要重新渲染
return false;
}
return true;
}
render() {
console.log("ClassOptimize渲染了");
return (
<div>
<h1>ClassOptimize 组件</h1>
<div>{this.state.counter}</div>
<button onClick={() => this.setState({
counter: Math.floor(Math.random() * 3 + 1)
})}>+1</button>
</div>
)
}
}
/utils/tools.js
/**
* 对两个对象进行一个浅比较,看是否相等
* obj1
* obj2
* 返回布尔值 true 代表两个对象相等, false 代表不想等
*/
export function objectEqual(obj1, obj2){
for(let prop in obj1){
if(!Object.is(obj1[prop],obj2[prop])){
// 进入此 if,说明有属性值不相等
// 只要有一个不相等,那么就应该判断两个对象不等
return false;
}
}
return true;
}
方式二
使用PureComponent跳过不必要的重新渲染,如果值相同就不会渲染
import React, { PureComponent } from 'react'
export default class ClassOptimize extends PureComponent {
constructor() {
super();
this.state = {
counter: 1
}
}
render() {
console.log("ClassOptimize渲染了");
return (
<div>
<h1>ClassOptimize 组件</h1>
<div>{this.state.counter}</div>
<button onClick={() => this.setState({
counter: 1
})}>+1</button>
</div>
)
}
}
方式三:扩展
import React, { PureComponent } from 'react'
export default class ClassOptimize extends PureComponent {
constructor() {
super();
this.state = {
stu: ['张三', '李四']
}
}
handleClick = () => {
// 新增用户
// 这样新增是没用的,视图不会更新,PureComponent进行的是浅层比较,它比较的是地址,看到地址一样就直接返回false阻止视图更新
/* this.state.stu.push('王五')
this.setState({
stu: this.state.stu
}) */
// 这样新增
const arr = [...this.state.stu]
arr.push('王五')
this.setState({
stu: arr
})
}
render() {
const li = this.state.stu.map((item, index) => (<li key={index}>姓名:{item}</li>))
return (
<div>
<h1>ClassOptimize 组件</h1>
<button onClick={this.handleClick}>新增用户</button>
<ul>
{li}
</ul>
</div>
)
}
}
下一篇讲函数组件渲染优化