Component与PureComponent对比源码分析

作者:有用网 阅读量:178 发布时间:2024-01-06
关键字

这篇文章主要介绍了Component与PureComponent对比源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Component与PureComponent对比源码分析文章都会有所收获,下面我们一起来看看吧。

官方文档

React.PureComponent
 与 
React.Component
很相似。两者的区别在于 
React.Component
 并未实现 
shouldComponentUpdate()
,而 
React.PureComponent
 中以浅层对比 prop 和 state 的方式来实现了该函数。

官方解释也很容易理解,

React.PureComponent
React.Component
中多实现了一个方法,就导致了在组件数据发生变化时,
React.PureComponent
会先进行和上一次的比较,如果相同,就不会再继续更新了。

对比

先看两者相同得地方 代码如下

class Box1 extends React.Component {
  render() {
    console.log('Box1 update');
    return <div>Box1: {this.props.count}</div>;
  }
}
class Box2 extends React.PureComponent {
  render() {
    console.log('Box2 update');
    return <div>Box2: {this.props.count}</div>;
  }
}

先制作2个对比的组件Box1与Box2, 然后制作一个父组件引入其中,并设置一个方法

export default () => {
  const [count, setCount] = React.useState(1);
  console.log('parent update');
  return (
    <div>
      <Box1 count={count}/>
      <Box2 count={count}/>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
};

此时,点击button按钮的时候,上述2个Box组件都会进行更新。

Component与PureComponent对比源码分析

这也是最基础的组件更新。

取消外部数据引入

class Box1 extends React.Component {
  render() {
    console.log('Box1 update');
    return <div>Box1</div>;
  }
}
class Box2 extends React.PureComponent {
  render() {
    console.log('Box2 update');
    return <div>Box2</div>;
  }
}
export default () => {
  const [count, setCount] = React.useState(1);
  console.log('parent update');
  return (
    <div>
      <Box1 />
      <Box2 />
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
};

取消Box组件内对外部count的引入

此时页面更新为

Component与PureComponent对比源码分析

此时会发现只有Box1重新刷新了一遍,而Box2未重新加载组件,也就是PureComponent内部做了浅比较相同的不会进行更新。

为什么被称为浅比较

浅比较是指对值类型进行比较,而稍微复杂一点的引用类型(Object),就无法进行判断了,react内部的更新都是浅比较。

export default () => {
  const [count, setCount] = React.useState({ num: 1 });
  console.log('parent update');
  const click = () => {
    const newCount = count;
    newCount.num = count.num + 1;
    setCount(newCount);
    console.log('update:', count)
  };
  return (
    <div>
      <Box1 />
      <Box2 />
      <button onClick={click}>+1</button>
    </div>
  );
};

此时,父组件内部的count为对象类型,此时进行更新时,页面不会触发任何更新,父组件也不会进行刷新(由于是引用类型,newCount发生数据变化时,count其实已经发生变化,但是页面并不会有任何的反应)。

Component与PureComponent对比源码分析

由图可见,子组件和父组件并没有进行刷新,均未打印。

小知识点

const的不可变定义也是只对于值类型而言,对于引用类型,还是依然可变。上述代码云清并不会报错。

说明

上述的一切代码都是建立在父组件自身更新的基础上子组件才会刷新,如果我将

setCount(count + 1)
改为
setCount(count + 0)
,那么,父组件本身不会进行刷新,子组件也就理所当然的不会有任何变化。

另类的不更新

这里的父组件刷新带动子组件刷新有一种例外的情况。代码如下

const Parent = ({ children }) => {
  const [count, setCount] = React.useState(1);

  console.log('parent update');
  return (
    <div>
      {children}
      <button onClick={() => setCount(count + 1)}>box2</button>
    </div>
  );
};

export default () => {
  return (
    <Parent>
      <Box1 />
      <Box2 />
    </Parent>
  );
};

将父组件抽离出来,子组件以children的形式引入。 此时页面点击发生的变化为

Component与PureComponent对比源码分析

会发现不管怎么点击,只有Parent组件进行刷新,子组件全部都毫无反应。


#发表评论
提交评论