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 相关文章推荐
使用基于jquery的gamequery插件做JS乒乓球游戏
Jul 31 Javascript
jQuery中将函数赋值给变量的调用方法
Mar 23 Javascript
Javascript实现代码折叠功能
Aug 25 Javascript
基于jQuery实现数字滚动效果
Jan 16 Javascript
angularjs中的$eval方法详解
Apr 24 Javascript
vue-loader教程介绍
Jun 14 Javascript
详解angular脏检查原理及伪代码实现
Jun 08 Javascript
解决vue中修改export default中脚本报一大堆错的问题
Aug 27 Javascript
vue项目中使用Svg的方法
Oct 24 Javascript
微信小程序websocket聊天室的实现示例代码
Feb 12 Javascript
JS设置自定义快捷键并实现图片上下左右移动
Oct 17 Javascript
jQuery冲突问题解决方法
Jan 19 jQuery
基于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类的注册与自动加载
2013/07/05 PHP
php批量删除数据库下指定前缀的表以prefix_为例
2014/08/24 PHP
ThinkPHP的常用配置选项汇总
2016/03/24 PHP
php ajax异步读取rss文档数据
2016/03/29 PHP
php实现微信支付之退款功能
2018/05/30 PHP
jQuery 判断元素上是否绑定了事件
2009/10/28 Javascript
js chrome浏览器判断代码
2010/03/28 Javascript
jQuery EasyUI API 中文文档 - ComboTree组合树
2011/10/11 Javascript
javascript跨域的4种方法和原理详解
2014/04/08 Javascript
原生javascript实现拖动元素示例代码
2014/09/01 Javascript
详谈js中window.location.search的用法和作用
2017/02/13 Javascript
Angular2之二级路由详解
2018/08/31 Javascript
基于vue实现web端超大数据量表格的卡顿解决
2019/04/02 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
前端Electron新手入门教程详解
2019/06/21 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
2019/11/11 Javascript
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python实现Pig Latin小游戏实例代码
2018/02/02 Python
Python自动化运维之Ansible定义主机与组规则操作详解
2019/06/13 Python
Pandas中DataFrame的分组/分割/合并的实现
2019/07/16 Python
python匿名函数用法实例分析
2019/08/03 Python
Python 装饰器@,对函数进行功能扩展操作示例【开闭原则】
2019/10/17 Python
Python 中如何实现参数化测试的方法示例
2019/12/10 Python
Django serializer优化类视图的实现示例
2020/07/16 Python
anaconda安装pytorch1.7.1和torchvision0.8.2的方法(亲测可用)
2021/02/01 Python
凯特·丝蓓英国官网:Kate Spade英国
2016/11/07 全球购物
美国最大婚纱连锁店运营商:David’s Bridal
2019/03/12 全球购物
美国床垫连锁店:Mattress Firm
2021/02/13 全球购物
制衣厂各岗位职责
2013/12/02 职场文书
领导的自我鉴定
2013/12/28 职场文书
迟到检讨书1000字
2014/01/15 职场文书
PHP控制循环操作的时间
2021/04/01 PHP
Python 用户输入和while循环的操作
2021/05/23 Python
新手初学Java网络编程
2021/07/07 Java/Android
关于python爬虫应用urllib库作用分析
2021/09/04 Python
Python使用Web框架Flask开发项目
2022/06/01 Python