React优化子组件render的使用


Posted in Javascript onMay 12, 2019

在react中,父组件的重新render会引发子组件的重新render,但是一些情况下我们会觉得这样做有些多余,比如:

  1. 父组件并未传递props给子组件
  2. 新传递的props渲染结果不变
class A extends React.Component {
  render() {
    console.log('render')
    return <div>这是A组件</div>
  }
}

class Main extends React.Component {
  render() {
    return (
      <div>
        // 点击button会让A不断调用render
        <button onClick={() => this.setState({ a: 1 })}>Main</button>
        <A />
      </div>
    )
  }
}

为了解决这个问题,需要分为ES6类组件和函数式组件两种:

类组件

使用shouldComponentUpdate来对props和state进行判断以此决定是否进行render

class A extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    //两次props对比
    return nextProps.a === this.props.a ? false : true
  }
  render() {
    console.log('render')
    return <div>这是A组件</div>
  }
}

class Main extends React.Component {
  // ...
  render() {
    return (
      <div>
        <button onClick={() => this.setState({ a: 1 })}>Main</button>
        <A a={this.state.a} />
      </div>
    )
  }
}

通过返回false来跳过这次更新

使用React.PureComponent,它与React.Component区别在于它已经内置了shouldComponentUpdate来对props和state进行浅对比,并跳过更新

//PureComponent
class A extends React.PureComponent {
  render() {
    console.log('render')
    return <div>这是A组件</div>
  }
}

class Main extends React.Component {
  state = {
    a: 1
  }
  render() {
    return (
      <div>
        <button onClick={() => this.setState({ a: 1 })}>Main</button>
        <A a={this.state.a} />
      </div>
    )
  }
}

函数组件

使用高阶组件React.memo来包裹函数式组件,它和类组件的PureComponent类似,也是对对props进行浅比较决定是否更新

const A = props => {
  console.log('render A')
  return <div>这是A组件</div>
}
// React.memo包裹A
const B = React.memo(A)

const Main = props => {
  const [a, setA] = useState(1)
  console.log('render Main')

  return (
    <div>
      // 通过setA(a + 1)让父组件重新render
      <button onClick={() => setA(a + 1)}>Main</button>
      // 一直传入相同的props不会让子组件重新render
      <B a={1} />
    </div>
  )
}

它的第二个参数接受一个两次props作为参数的函数,返回true则禁止子组件更新

其他

上面提到的浅比较就是根据内存地址判断是否相同:

// extends React.Component
class A extends React.Component {
  render() {
    console.log('render A')
    console.log(this.props)
    return <div>这是组件A</div>
  }
}

class Main extends React.Component {
  test = [1, 2, 3]
  render() {
    console.log('render Main')
    return (
      <div>
        <button
          onClick={() => {
            // 父组件render
            this.setState({})
            this.test.push(4)
          }}
        >
          Main
        </button>
        <A test={this.test} />
      </div>
    )
  }
}

结果是:

使用React.component:

React优化子组件render的使用

使用React.PureComponent:

React优化子组件render的使用

使用React.component,点击之后子组件重新render。改为React.PureComponent之后,点击button子组件并不会render。也因此,PureComponent根据前后内存地址判断是否相等,所以向子组件传递函数作为props时,使用内联箭头函数的形式将会导致子组件的重新render;所以可以用箭头函数作为成员变量的形式再将函数引用作为props传递。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript中的Split使用方法与技巧
Mar 09 Javascript
jquery select下拉框操作的一些说明
Apr 02 Javascript
详解JavaScript中的构造器Constructor模式
Jan 14 Javascript
js实现5秒倒计时重新发送短信功能
Feb 05 Javascript
基于zTree树形菜单的使用实例
Dec 25 Javascript
使用JS获取SessionStorage的值
Jan 12 Javascript
JS实现读取xml内容并输出到div中的方法示例
Apr 19 Javascript
对 Vue-Router 进行单元测试的方法
Nov 05 Javascript
mpvue 单文件页面配置详解
Dec 02 Javascript
在JavaScript中如何访问暂未存在的嵌套对象
Jun 18 Javascript
Node对CommonJS的模块规范
Nov 06 Javascript
解决vue请求接口第一次成功,第二次失败问题
Sep 08 Javascript
基于elementUI使用v-model实现经纬度输入的vue组件
May 12 #Javascript
vue组件中watch props根据v-if动态判断并挂载DOM的问题
May 12 #Javascript
用js简单提供增删改查接口
May 12 #Javascript
electron-vue利用webpack打包实现多页面的入口文件问题
May 12 #Javascript
vue中axios实现数据交互与跨域问题
May 12 #Javascript
jquery3和layui冲突导致使用layui.layer.full弹出全屏iframe窗口时高度152px问题
May 12 #jQuery
JS块级作用域和私有变量实例分析
May 11 #Javascript
You might like
一个目录遍历函数
2006/10/09 PHP
PHP随机数生成代码与使用实例分析
2011/04/08 PHP
谨慎使用PHP的引用原因分析
2012/09/06 PHP
php读取大文件示例分享(文件操作类)
2014/04/13 PHP
PHP获取客户端及服务器端IP的封装类
2016/07/21 PHP
PHP常用算法和数据结构示例(必看篇)
2017/03/15 PHP
PHP mkdir创建文件夹实现方法解析
2020/11/13 PHP
一个用javascript写的select支持上下键、首字母筛选以及回车取值的功能
2009/09/09 Javascript
jQuery 学习第六课 实现一个Ajax的TreeView
2010/05/17 Javascript
jquery入门—编写一个导航条(可伸缩)
2013/01/07 Javascript
JSF中confirm弹出框的用法示例介绍
2014/01/07 Javascript
jQuery实现动画效果的简单实例
2014/01/27 Javascript
jQuery中事件对象e的事件冒泡用法示例介绍
2014/04/25 Javascript
ExtJS4给Combobox设置列表中的默认值示例
2014/05/02 Javascript
javascript里使用php代码实例
2014/12/13 Javascript
JS实现兼容各浏览器解析XML文档数据的方法
2015/06/01 Javascript
javascript实现网站加入收藏功能
2015/12/16 Javascript
深入学习jQuery Validate表单验证
2016/01/18 Javascript
JS获取地址栏参数的两种方法(简单实用)
2016/06/14 Javascript
第五篇Bootstrap 排版
2016/06/21 Javascript
Bootstrap如何创建表单
2016/10/21 Javascript
Vue CLI 3搭建vue+vuex最全分析(推荐)
2018/09/27 Javascript
vue调试工具vue-devtools安装及使用方法
2018/11/07 Javascript
JavaScript实现新年倒计时效果
2018/11/17 Javascript
python 输出上个月的月末日期实例
2018/04/11 Python
python write无法写入文件的解决方法
2019/01/23 Python
Python 转换文本编码实现解析
2019/08/27 Python
jupyter notebook插入本地图片的实现
2020/04/13 Python
CSS3 实现雷达扫描图的示例代码
2020/09/21 HTML / CSS
HTML5 通过Vedio标签实现视频循环播放的示例代码
2020/08/05 HTML / CSS
德国古洛迷亚百货官网:GALERIA Kaufhof
2017/06/20 全球购物
The North Face北面英国官网:美国著名户外品牌
2017/12/13 全球购物
2015年个人工作总结报告
2015/04/25 职场文书
幼儿园校车安全责任书
2015/05/08 职场文书
公诉意见书范文
2015/06/05 职场文书
小英雄雨来观后感
2015/06/09 职场文书