Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >React16的memo函数有啥用

React16的memo函数有啥用

原创
作者头像
挥刀北上
修改于 2020-08-18 10:13:32
修改于 2020-08-18 10:13:32
1.2K00
代码可运行
举报
文章被收录于专栏:Node.js开发Node.js开发
运行总次数:0
代码可运行

React16的memo和PureComponent作用类似,只不过前者只适用于函数组件,后者适应于类组件。

关于两者的作用,我们先从PureComponent说起,在了解PureComponent之前要先了解shouldComponentUpdate函数,在类组件中有一个叫做shouldComponentUpdate的生命周期函数,这个函数可以通过返回true或false来决定当前组件是否重新渲染。

而PureComponent自带shouldComponentUpdate函数,PureComponent自带的shouldComponentUpdate函数会在当前组件的props或者state发生变化时,对props或者state进行浅对比,如果相同则不进行重新渲染,反之则会进行渲染。

说到这里来了解一下浅对比,啥叫浅对比呢,类似于浅拷贝,具体的内容大家可以去百度,这里不做赘述,只做简单说明,举个例子,看代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三'
      }, {
        body: '新冠病毒', author: '李四'
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.setState((prevState, props) => {
        return {
          commentList: [{
            body: '大三岁', author: '张三'
          }, {
              body: '新冠1病毒', author: '李四'
          }]
        }
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}
function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}

阅读源码,我们定义了两个组件,CommentList组件与Comment组件,CommentList组件内部的state是一个数组,每条数据用Comment来渲染。我们在componentWillMount设置定时器模拟数据发生变化,我们看到第二条数据的body发生变化了,所以对应的comment组件应该重新渲染,但是我们发现所有Comment组件都重新渲染了。这不利于我们页面的性能优化,咋办呢?

此时我们可以借助memo或者PureComponent来实现只让该渲染的组件渲染,啥是该渲染的组件呢?那就是props或者state发生变化的组件,那变化的标准是怎么样的呢?

来看代码,用memo来实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三' 
      }, {
        body: '新冠病毒', author: '李四' 
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.setState((prevState, props) => {
        return {
          commentList: [{
            body: '大三岁', author: '张三'
          }, {
              body: '新冠1病毒', author: '李四'
          }]
        }
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}



function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}

// 第一种方式 用memo包裹函数组件
Comment = memo(Comment)

用PureComponent来实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三' 
      }, {
        body: '新冠病毒', author: '李四' 
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.setState((prevState, props) => {
        return {
          commentList: [{
            body: '大三岁', author: '张三'
          }, {
              body: '新冠1病毒', author: '李四'
          }]
        }
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}

class Comment extends React.PureComponent {
  constructor() {
    super()
  }
  render() {
    console.log('渲染了')
    const props = this.props
    return <div>
      <p>{props.body}</p>
      <p>{props.author}</p>
    </div>
  }
}

阅读源码,我们分别用memo和PureComponent改造了代码,并且运行的话,只有该渲染的组件发生了渲染。

渲染的组件前后的props发生变化的组件才会重新渲染,来看一下props或者state发生变化的标准:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{body: '新冠病毒', author: '李四'} 

{body: '新冠1病毒', author: '李四'} 

上面两个对象进行浅对比body发生变化,所以会渲染,而另一个组件数据没变所以没有重新渲染,从而提高了页面性能。

以上便是memo的作用了,但是这里有一个问题,那就是如果props中的某一个属性是引用数据类型,这个引用数据发生改变,但是引用未变,组件是不会重新渲染的,首先我们看下不使用memo的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三',arr:[]
      }, {
        body: '新冠病毒', author: '李四',arr:[]
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.state.commentList[0].arr.push(999)
      this.setState({ commentList: this.state.commentList})
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}

// 

function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}

上面的代码,我们没有使用memo,Comment的props发生变化后,所有的Comment组件都重新渲染了,如图:

效果截图
效果截图

上图红框处显示了组件重新渲染了,然后我们用memo改造代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React,{memo} from "react";
import ReactDOM from 'react-dom';
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      commentList: [{
        body: '大三岁', author: '张三',arr:[]
      }, {
        body: '新冠病毒', author: '李四',arr:[]
      }]
    }
  }

  componentWillMount() {
    setTimeout(() => {
      this.state.commentList[0].arr.push(999)
      this.setState({ commentList: this.state.commentList})
    }, 1000)
  }

  render() {
    return (
      <div>
        {
          this.state.commentList.map((item, index) => {
            return <Comment {...item} key={index} />
          })
        }
      </div>
    )

  }
}

// 

function Comment(props) {
  console.log('渲染了', props)
  return <div>
    <p>{props.body}</p>
    <p>{props.author}</p>
    <p>{props.arr.length}</p>
  </div>
}


Comment = memo(Comment)

此时看效果:

效果截图
效果截图

上图展示显示了,虽然组件的props发生了变化,但是组件为重新渲染。

那这个bug怎么解决呢,很简单,不要直接修改完数据直接使用,而是修改完后深拷贝一下再去调用setState。

所以在使用memo和PureComponent时大家需要特别注意,总结一下:

1、memo和PureComponent的作用提高渲染性能,避免不必要的渲染。

2、memo和PureComponent的原理是通过浅拷贝来实现的。

3、通过案例演示了memo的作用。

4、memo的缺点,当props或state中的属性有引用属性时需要注意,修改完成后进行一下深拷贝在调用setState。

以上便是使用memo的一下注意事项,希望对你有所帮助。

参考:你真的了解浅比较么?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
React16中的Component与PureComponent
React中用类的方式声明组件的时候,一般需要继承Component这个类,但是在React16版本中增加了一个PureComponent类,这两个类有什么区别呢?
挥刀北上
2020/02/20
1.3K0
性能!!让你的 React 组件跑得再快一点
React 基于虚拟 DOM 和高效 Diff 算法的完美配合,实现了对 DOM 最小粒度的更新。大多数情况下,React 对 DOM 的渲染效率足以我们的业务日常。但在个别复杂业务场景下,性能问题依然会困扰我们。此时需要采取一些措施来提升运行性能,其很重要的一个方向,就是避免不必要的渲染(Render)。
政采云前端团队
2019/12/20
6470
性能!!让你的 React 组件跑得再快一点
[边学边练]用简单实例学习React
学习之路不可停止,最近在玩 React。也动手尝试写了一个实例。借此整理总结下初步学习 React 的一些基础知识。因为这几天比较忙,没那么多时间,所以实例和文章没有很细致。如果大家发现文章有错误的地方,请多谅解。有什么更新的建议,欢迎在评论区指出。该文章主要是大概讲下和快速上手使用,如果深入,要靠自己探索,后期我也会补充文章。
守候i
2018/08/27
1.3K0
[边学边练]用简单实例学习React
细说React组件性能优化
React 组件性能优化的核心是减少渲染真实 DOM 节点的频率,减少 Virtual DOM 比对的频率。如果子组件未发生数据改变不渲染子组件。
xiaofeng123aa
2022/10/18
1.5K0
快速了解React 16新特性
前一段时间React v16.0发布了,作为react骚年,我们当然要关注版本更新之后,react新增了哪些特性呢?
江米小枣
2020/06/16
1.4K0
快速了解React 16新特性
高频react面试题自检
展示组件关心组件看起来是什么。展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态。
beifeng1996
2022/11/14
9390
React 16 - 基础
历史背景及特性 问题根源 传统 UI 操作(DOM API)关注太多细节 应用程序状态分散在各处,难以追踪和维护 React 思想 UI 细节:始终整体“刷新”页面,无需关心细节 数据模型: Flux 架构:单向数据流 实现 Redux MobX 以组件方式考虑 UI 构建 组件化思想 class CommentBox extends Component { render() { return ( <div className="commentBox">
Cellinlab
2023/05/17
4520
React 16 - 基础
ReactJS实战之组件和Props详解
组件可以将UI切分成一些独立的、可复用的部件,这样就只需专注于构建每一个单独的部件。
JavaEdge
2021/03/14
1.1K0
React 16 新特性全解(上)
本次系列分上下两篇文章,上主要介绍从v16.0~ 16.4的新特性,下主要介绍16.5~16.8。下面就开始吧~
前端迷
2019/07/12
1.6K0
React 16 新特性全解(上)
React入门学习笔记
这里的constructor()初始化了props,state.value=null;当点击后,state.value=X;
Mirror王宇阳
2020/12/16
2.7K0
[译]使用React.memo()来优化React函数组件的性能
React核心开发团队一直都努力地让React变得更快。在React中可以用来优化组件性能的方法大概有以下几种:
进击的大葱
2022/08/22
2.1K0
[译]使用React.memo()来优化React函数组件的性能
番外篇:入门React
原生js代码乱七八糟的时候,那就来体验一下React。 Tip:内容有点乱,秘籍在最后
用户3467126
2019/07/03
1.5K0
番外篇:入门React
React16 新特性
于 2017.09.26 Facebook 发布 React v16.0 版本,时至今日已更新到 React v16.6,且引入了大量的令人振奋的新特性,本文章将带领大家根据 React 更新的时间脉络了解 React16 的新特性。
前端迷
2019/08/27
1.2K0
一天梳理完React所有面试考察知识点
在shouldComponentUpdate()判断中,有一个有意思的问题,解释为什么 React setState() 要用不可变值
beifeng1996
2022/10/06
2.9K0
React 开发要知道的 34 个技巧
原理:子组件里面利用 props 获取父组件方法直接调用,从而改变父组件的值 注意: 此方法和 props 大同小异,都是 props 的应用,所以在源码中没有举例
前端老王
2020/09/23
1.6K0
React 组件优化方案
如果你知道在什么情况下你的组件不需要更新,你可以在 shouldComponentUpdate 中返回 false 来跳过整个渲染过程。其包括该组件的 render 调用以及之后的操作。该方法会在 重新渲染前 被触发,其默认实现总是返回 true。
多云转晴
2020/02/17
3.3K0
React 组件化开发(一)
写react和传统的js差不多。只是有一个设计思想贯穿了整个框架。用一个公式来表达就是:
一粒小麦
2019/07/18
2.5K0
React 组件化开发(一)
React App 性能优化总结
在 React 内部,React 会使用几项巧妙的小技术,来优化计算更新 UI 时,所需要的最少的更新 DOM 的操作。在大多数情况下,即使你没有针对性能进行专项优化,React 依然很快,但是仍有一些方法可以加速 React 应用程序。本文将介绍一些可用于改进 React 代码的有效技巧。
前端迷
2019/07/19
7.9K0
Web 性能优化: 使用 React.memo() 提高 React 组件性能
React.js 核心团队一直在努力使 React 变得更快,就像燃烧的速度一样。为了让开发者能够加速他们的 React 应用程序,为此增加了很多工具:
前端小智@大迁世界
2019/03/20
6.1K0
Web 性能优化: 使用 React.memo() 提高 React 组件性能
你需要的react面试高频考察点总结
函数式组件(Functional component)根本没有实例instance。类组件(Class component)有实例instance,但是永远也不需要直接创建一个组件的实例,因为React帮我们做了这些。
beifeng1996
2022/11/08
3.8K0
相关推荐
React16中的Component与PureComponent
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验