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 相关文章推荐
同一个表单 根据要求递交到不同页面的实现方法小结
Aug 05 Javascript
javascript动态添加表格数据行(ASP后台数据库保存例子)
May 08 Javascript
基于BootStrap Metronic开发框架经验小结【四】Bootstrap图标的提取和利用
May 12 Javascript
RequireJs的使用详解
Feb 19 Javascript
jQuery实现键盘回车搜索功能
Jul 25 jQuery
VueJs使用Amaze ui调整列表和内容页面
Nov 30 Javascript
JS表单传值和URL编码转换
Mar 03 Javascript
vue首次赋值不触发watch的解决方法
Sep 11 Javascript
vue+django实现一对一聊天功能的实例代码
Jul 17 Javascript
浅析Vue下的components模板使用及应用
Nov 27 Javascript
jQuery实现飞机大战小游戏
Jul 05 jQuery
javascript实现倒计时关闭广告
Feb 09 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
用phpmyadmin更改mysql5.0登录密码
2008/03/25 PHP
PHP FTP操作类代码( 上传、拷贝、移动、删除文件/创建目录)
2014/05/10 PHP
Windows 下安装 swoole 图文教程(php)
2017/06/05 PHP
php-fpm服务启动脚本的方法
2018/04/27 PHP
Google Map Api和GOOGLE Search Api整合实现代码
2009/07/18 Javascript
整理的比较全的event对像在ie与firefox浏览器中的区别
2013/11/25 Javascript
js清除input中type等于file的值域(示例代码)
2013/12/24 Javascript
jQuery获取上传文件的名称的正则表达式
2015/05/21 Javascript
javascript实现自动输出文本(打字特效)
2015/08/27 Javascript
JS实现仿FLASH效果的竖排导航代码
2015/09/15 Javascript
简单谈谈json跨域
2016/03/13 Javascript
jQuery焦点图左右转换效果
2016/12/12 Javascript
移动端利用H5实现压缩图片上传功能
2017/03/29 Javascript
slideToggle+slideup实现手机端折叠菜单效果
2017/05/25 Javascript
实时监控input框,实现输入框与下拉框联动的实例
2018/01/23 Javascript
Vue组件中prop属性使用说明实例代码详解
2018/05/31 Javascript
Vue中对拿到的数据进行A-Z排序的实例
2018/09/25 Javascript
jQuery使用$.extend(true,object1, object2);实现深拷贝对象的方法分析
2019/03/06 jQuery
vue使用lodop打印控件实现浏览器兼容打印的方法
2021/02/07 Vue.js
Python创建二维数组实例(关于list的一个小坑)
2017/11/07 Python
Numpy之reshape()使用详解
2019/12/26 Python
canvas 基础之图像处理的使用
2020/04/10 HTML / CSS
MUGLER官方网站:蒂埃里·穆勒香水
2019/11/26 全球购物
机械设计专业应届生求职信
2013/11/21 职场文书
金属材料工程毕业生个人的自我评价
2013/11/28 职场文书
教师自荐信
2013/12/10 职场文书
中医专业职业生涯规划书范文
2014/01/04 职场文书
岗位工作说明书
2014/07/29 职场文书
民主评议党员自我评价材料
2014/09/18 职场文书
校本课程教学计划
2015/01/19 职场文书
2016年小学优秀班主任事迹材料
2016/02/29 职场文书
物业管理交接协议书
2016/03/24 职场文书
springcloud之Feign超时问题的解决
2021/06/24 Java/Android
Python保存并浏览用户的历史记录
2022/04/29 Python
app场景下uniapp的扫码记录
2022/07/23 Java/Android
Linux在两个服务器直接传文件的操作方法
2022/08/05 Servers