😂Github

# React 性能优化(一): 减少不必要的组件更新

在 React 里会遇到这样一个场景: 父组件的状态发生变化会触发父组件的更新, 随后连同子组件一起更新.可是如果子组件没有和父组件产生依赖, 更新子组件其实是没有必要的.举个例子如下:

class Son extends React.Component {
  render() {
    console.log("触发儿子组件render");
    return <p>我是儿子</p>;
export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      n: 1,
  render() {
    return (
        <p>我是爸爸</p>
        <p>{this.state.n}</p>
        <button
          onClick={() => {
            this.setState({ n: this.state.n + 1 });
        </button>
        <Son />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

在 console 里可以看到, 每当 +1 按钮被点击, Son 组件的 render 函数就会被执行一次.那我们应该通知 React 不要更新子组件.

# shouldComponentUpdate

这里 是这个钩子的详细定义和使用.

class Son extends React.Component {
  shouldComponentUpdate() {
    return false;
  render() {
    console.log("触发儿子组件render");
    return <p>我是儿子</p>;
export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      n: 1,
  render() {
    return (
        <p>我是爸爸</p>
        <p>{this.state.n}</p>
        <button
          onClick={() => {
            this.setState({ n: this.state.n + 1 });
        </button>
        <Son />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# PureComponent

如果不想每次手动调用上面的钩子, React 提供了 PureComponent 来解决同样的问题:

class Son1 extends React.PureComponent {
  render() {
    console.log("触发儿子组件render");
    return <p>我是儿子</p>;
export default class App1 extends React.Component {
  constructor() {
    super();
    this.state = {
      n: 1,
  render() {
    return (
        <p>我是爸爸</p>
        <p>{this.state.n}</p>
        <button
          onClick={() => {
            this.setState({ n: this.state.n + 1 });
        </button>
        <Son1 />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

注意

值得一提的是, PureComponent shouldComponentUpdate props 做得只是浅层比较,不是深层比较,如果 props 是一个深层对象,就容易产生问题。

比如,两次渲染传入的某个 props 都是同一个对象,但是对象中某个属性的值不同,这在 PureComponent 眼里, props 没有变化,不会重新渲染,但是这>明显不是我们想要的结果。

# 函数组件使用

在函数组件里, React 提供了 React.memo 来实现自定义更新:

const Son = React.memo((props) => {
  console.log("触发儿子更新");
  return <div>我是儿子{props.n}</div>;
});
export default class App1 extends React.Component {
  constructor() {
    super();
    this.state = {
      n: 1,
  render() {
    return (
        <p>我是爸爸</p>
        <p>{this.state.n}</p>
        <button
          onClick={() => {
            this.setState({ n: this.state.n + 1 });
        </button>
        <Son />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29