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 面试题随笔
Mar 31 Javascript
一个简单的jquery进度条示例
Apr 28 Javascript
详解JavaScript语法对{}处理的坑爹之处
Jun 05 Javascript
浅谈JavaScript 中有关时间对象的方法
Aug 15 Javascript
Bootstrap中glyphicons-halflings-regular.woff字体报404错notfound的解决方法
Jan 19 Javascript
vue 里面使用axios 和封装的示例代码
Sep 01 Javascript
基于bootstrop常用类总结(推荐)
Sep 11 Javascript
js 索引下标之li集合绑定点击事件
Jan 12 Javascript
JavaScript常见鼠标事件与用法分析
Jan 03 Javascript
小程序getLocation需要在app.json中声明permission字段
Apr 04 Javascript
Vue2.0 $set()的正确使用详解
Jul 28 Javascript
如何通过简单的代码描述Angular父组件、子组件传值
Apr 07 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
六酷社区论坛HOME页清新格调免费版 下载
2007/03/07 PHP
PHP操作文件类的函数代码(文件和文件夹创建,复制,移动和删除)
2011/11/10 PHP
PHP输出九九乘法表代码实例
2015/03/27 PHP
CI框架实现优化文件上传及多文件上传的方法
2017/01/04 PHP
PHP new static 和 new self详解
2017/02/19 PHP
jquery 图片轮换效果
2010/07/29 Javascript
Javascript Throttle &amp; Debounce应用介绍
2013/03/19 Javascript
利用webqq协议使用python登录qq发消息源码参考
2013/04/08 Javascript
浅析JavaScript原型继承的陷阱
2013/12/03 Javascript
jQuery实现的简单提示信息插件
2015/12/08 Javascript
原生js实现网易轮播图效果
2020/04/10 Javascript
vue实现可增删查改的成绩单
2016/10/27 Javascript
vue.js利用Object.defineProperty实现双向绑定
2017/03/09 Javascript
Vue+jquery实现表格指定列的文字收缩的示例代码
2018/01/09 jQuery
详解vue配置后台接口方式
2019/03/29 Javascript
Vue组件之高德地图地址选择功能的实例代码
2019/06/21 Javascript
vue语法自动转typescript(解放双手)
2019/09/18 Javascript
[01:15:12]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#4Newbee VS CDEC
2016/03/03 DOTA
[01:38]【DOTA2亚洲邀请赛】Sumail——梦开始的地方
2017/03/03 DOTA
[45:32]Liquid vs LGD 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
Python字典操作简明总结
2015/04/13 Python
python实现在windows服务中新建进程的方法
2015/06/30 Python
pycharm debug功能实现跳到循环末尾的方法
2018/11/29 Python
Python 运行.py文件和交互式运行代码的区别详解
2019/07/02 Python
python中将两组数据放在一起按照某一固定顺序shuffle的实例
2019/07/15 Python
Python绘制数码晶体管日期
2021/02/19 Python
最新远光软件笔试题面试题内容
2013/11/08 面试题
生日宴会答谢词
2014/01/09 职场文书
上级检查欢迎词
2014/01/18 职场文书
社区党务公开实施方案
2014/03/18 职场文书
贷款委托书
2014/08/01 职场文书
英语教师个人工作总结
2015/02/09 职场文书
2015年初三班主任工作总结
2015/05/21 职场文书
Python+Appium自动化测试的实战
2021/06/30 Python
SQL Server内存机制浅探
2022/04/06 SQL Server
SQL Server 忘记密码以及重新添加新账号
2022/04/26 SQL Server