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 getElementsByTagName
Jan 31 Javascript
SOSO地图JS画出标注和中心点以html形式运行
Aug 09 Javascript
js函数定时器实现定时读取系统实时连接数
Apr 30 Javascript
jQuery中:checkbox选择器用法实例
Jan 03 Javascript
js实现汉字排序的方法
Jul 23 Javascript
JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
Dec 13 Javascript
Bootstrap导航栏各元素操作方法(表单、按钮、文本)
Dec 28 Javascript
jQuery 移动端artEditor富文本编辑器
Jan 11 Javascript
JS hashMap实例详解
May 26 Javascript
JavaScript累加、迭代、穷举、递归等常用算法实例小结
May 08 Javascript
jQuery时间戳和日期相互转换操作示例
Dec 07 jQuery
React更新渲染原理深入分析
Dec 24 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
php set_time_limit(0) 设置程序执行时间的函数
2010/05/26 PHP
php str_getcsv把字符串解析为数组的实现方法
2017/04/05 PHP
一个基于jquery的文本框记数器
2012/09/19 Javascript
jquery 延迟执行实例介绍
2013/08/20 Javascript
JavaScript AJAX之惰性载入函数
2014/08/27 Javascript
JS取得绝对路径的实现代码
2015/01/16 Javascript
IE及IE6浏览器中判断JS文件加载成功失败的方法
2015/02/18 Javascript
JS实现复制功能
2017/03/01 Javascript
Vue中的v-cloak使用解读
2017/03/27 Javascript
Angular中ng-repeat与ul li的多层嵌套重复问题
2017/07/24 Javascript
使用vue的v-for生成table并给table加上序号的实例代码
2017/10/27 Javascript
web3.js增加eth.getRawTransactionByHash(txhash)方法步骤
2018/03/15 Javascript
vue项目中仿element-ui弹框效果的实例代码
2019/04/22 Javascript
vue实现分页的三种效果
2020/06/23 Javascript
[51:34]Ti4主赛事胜者组 DK vs EG 2
2014/07/19 DOTA
python实现图片批量剪切示例
2014/03/25 Python
Python的Flask框架中实现登录用户的个人资料和头像的教程
2015/04/20 Python
python利用lxml读写xml格式的文件
2017/08/10 Python
使用tensorflow实现AlexNet
2017/11/20 Python
django静态文件加载的方法
2018/05/20 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
Pandas聚合运算和分组运算的实现示例
2019/10/17 Python
python3+selenium获取页面加载的所有静态资源文件链接操作
2020/05/04 Python
HTML5 客户端数据库简易使用:IndexedDB
2019/12/19 HTML / CSS
日本7net购物网:书籍、漫画、杂志、DVD、游戏邮购
2017/02/17 全球购物
欧洲最大的品牌水上运动服装和设备在线零售商:Wuituit Outlet
2018/05/05 全球购物
英国露营设备和户外服装购物网站:Simply Hike
2019/05/05 全球购物
智乐游戏测试笔试题
2014/05/21 面试题
学生自我鉴定
2013/12/18 职场文书
《盘古开天地》教学反思
2014/02/28 职场文书
《山谷中的谜底》教学反思
2014/04/26 职场文书
没有孩子的离婚协议书怎么写
2014/09/17 职场文书
支部书记四风问题自我剖析材料
2014/09/29 职场文书
优秀党员先进事迹材料
2014/12/18 职场文书
幼儿园小班个人工作总结
2015/02/12 职场文书
2015年采购部工作总结
2015/04/23 职场文书