先来说说Context的作用

react之类的mvvm框架有个痛点想必大家都遇到过,那就是祖孙组件之间的通信

现在组件之间的通信规范是:

  • 父 -> 子:属性绑定props
  • 子 -> 父:事件广播(vue之类的emit)react那还是调用父类的props[fn]

仅仅是父子两个组件之间这没有问题
可是祖孙组件之间呢?

react中有个虫洞的概念,相当于直通车,组件【祖先】=> 组件【孙子】,而不需要中间的组件来代理props

下面就先介绍下高端的虫洞(直通车)

直接show code

三个组件App.js,Son.js,GrandSon.js,下面介绍的是用虫洞从App props直通GrandSon,而不需要Son来做代理属性

// App.js的代码import React from 'react';
import Son from './son';
import PropTypes from 'prop-types';class App extends React.Component{constructor(){super();this.state = {grandSonDesc: 'i am grandSonDesc'};}getChildContext(){return {grandSonDesc: this.state.grandSonDesc}}render(){return <Son />}
}App.childContextTypes = {grandSonDesc: PropTypes.string
}export default App;
复制代码
// Son.jsimport React from 'react';
import GrandSon from './grandSon';const Son = () => {return <GrandSon />
}export default Son;
复制代码
// GrandSon.jsimport React from 'react';
import PropTypes from 'prop-types';class GrandSon extends React.Component{render(){return <div>{this.context.grandSonDesc}</div>}
}GrandSon.contextTypes = {grandSonDesc: PropTypes.string
};export default GrandSon;
复制代码

至此就实现了虫洞了,可是需要注意两点:

  • GrrandSon不能为纯函数组件,这样是不能注入的
  • App组件和GrandSon组件需要定义类属性contextTypes,App组件需要定义getChildContext

那么问题来了,为啥要声明contextTypes? 原因是,GrandSon组件除了App这个爷爷组件外,还有Son这个爸爸组件。那么grandSonDesc是从哪个组件继承而来呢,contextTypes就是做这个标识作用,而且多个父组件的context会做merge,也是根据定义contextTypes来的

好的,到这里感觉很爽,虫洞直通车传输props,但是我要说的是,这个实现在react17将被废弃!!!

为何老版本虫洞将被废弃?

如果一个属性将被废弃,多半是跟它的性能有关了,可以试想下,虫洞传输props,其实son组件没有任何更新,那么当grandSonDesc变化时,Son组件会不会被更新?直接show code吧

// App.jsimport React from 'react';
import Son from './son';
import PropTypes from 'prop-types';class App extends React.Component{constructor(){super();this.state = {grandSonDesc: 'i am grandSonDesc'};}componentDidMount(){setTimeout(() => {this.setState({grandSonDesc: 'i am grandSonDesc啊啊啊啊啊啊啊啊'});}, 3000);}getChildContext(){return {grandSonDesc: this.state.grandSonDesc}}render(){return <Son />}
}App.childContextTypes = {grandSonDesc: PropTypes.string
}export default App;
复制代码
// Son.jsimport React from 'react';
import GrandSon from './grandSon';class Son extends React.Component{componentDidUpdate(){console.log('son updated!');}render(){return <GrandSon />}
}export default Son;
复制代码
// GrandSon.jsimport React from 'react';
import PropTypes from 'prop-types';class GrandSon extends React.Component{componentDidUpdate(){console.log('grandson updated!');}render(){return <div>{this.context.grandSonDesc}</div>}
}GrandSon.contextTypes = {grandSonDesc: PropTypes.string
};export default GrandSon;
复制代码

在版本的代码中,App.js在三秒钟之后去更新grandSonDesc,然后在Son和GrandSon组件中加上componentDidUpdate更新之后的log,来看一下控制台输出

三秒之后GrandSon的显示变成了i am grandSonDesc啊啊啊啊啊啊啊啊,而控制台输出son updated

这说明Son组件也被更新了,那么虫洞如果中间层组件比较多的话,岂不是很浪费性能吗?

二代虫洞

那么既然性能不好,世界顶级前端团队就要开始优化了,那么就有了二代虫洞,直接上代码介绍下二代虫洞吧,还是原来的配方App+Son+GrandSon,唯一多的是一个context的配置文件

// App.jsimport React from 'react';
import Son from './son';
import Context from './context';
import PropTypes from 'prop-types';class App extends React.Component {constructor(){super();this.state = {grandSonDesc: 'i am grandSon'};}render(){return (<div className="App"><Context.Provider value={this.state}><Son /></Context.Provider></div>);}
}App.contextType = Context;export default App;
复制代码
// Son.jsimport React, { PureComponent } from 'react';
import GrandSon from './grandSon';
import PropTypes from 'prop-types';class Son extends PureComponent{render(){return <GrandSon />}
}export default Son;
复制代码
// GrandSon.jsimport React, { PureComponent } from 'react';
import Context from './context';class GrandSon extends PureComponent{render(){return <div><Context.Consumer>{value => value.grandSonDesc}</Context.Consumer></div>}
}export default GrandSon
复制代码
// context.jsimport { createContext } from 'react';let Context = createContext();export default Context;
复制代码

代码敲完了,可以start看看效果了,可以发现照样跑起来了

那么问题来了,你说一代虫洞性能差,凭什么嘛?

// App.jsimport React from 'react';
import Son from './son';
import Context from './context';
import PropTypes from 'prop-types';class App extends React.Component {constructor(){super();this.state = {grandSonDesc: 'i am grandSon'};}componentDidMount(){setTimeout(() => {this.setState({grandSonDesc: 'i am grandSon啊啊啊啊啊啊啊啊啊啊'});}, 3000);}render(){return (<div className="App"><Context.Provider value={{grandSonDesc: this.state.grandSonDesc}}><Son /></Context.Provider></div>);}
}App.contextType = Context;export default App;复制代码
// Son.jsimport React, { PureComponent } from 'react';
import GrandSon from './grandSon';
import PropTypes from 'prop-types';class Son extends PureComponent{componentDidUpdate(){console.log('son updated');}render(){return <GrandSon />}
}export default Son;
复制代码
// GrandSon.jsimport React, { PureComponent } from 'react';
import Context from './context';class GrandSon extends PureComponent{componentDidUpdate(){console.log('grandson updated');}render(){return <div><Context.Consumer>{value => value.grandSonDesc}</Context.Consumer></div>}
}export default GrandSon
复制代码

可以发现,3秒之后grandSonDesc变了,两个子组件的componentDidUpdated都没进

这就是两种虫洞的实现方式,到这里差不多讲完了,关于更多新版context的用法可以参考官网 reactjs.org/docs/contex…

转载于:https://juejin.im/post/5cdbd3f9e51d453a393af504

React性能优化之Context相关推荐

  1. react性能优化方案_React灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...

    react性能优化方案 在我以前的文章中,我研究了一个虚拟的交易引擎,并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较. 在文章的结尾,我写道: 我怀疑随着Node.js的 ...

  2. [react] 你知道的react性能优化有哪些方法?

    [react] 你知道的react性能优化有哪些方法? shouldComponentUpdate PureComponent :Class Component React.Memo :Functio ...

  3. React性能优化记录(不定期更新)

    React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...

  4. React性能优化SCU | PureComponent | memo

    文章目录 React性能优化SCU React更新机制 render函数被调用 PureComponent 高阶组件memo React性能优化SCU React更新机制 我们在前面文章已经讲解过Re ...

  5. Airbnb 爱彼迎房源详情页中的 React 性能优化

    Airbnb 爱彼迎工程师和数据科学家将定期和大家分享移动开发.系统架构.数据科学及人工智能等领域的技术探索和经验心得. 正文从这开始-- 在一些容易被忽视但又非常重要的场景,可能会有许多严重影响性能 ...

  6. React性能优化(完整版)

    我的博客 http://wangxince.site/my-demo-markdown/ React 性能优化 1.减少 render 次数 shouldComponentUpdate PureCom ...

  7. react 组件遍历】_从 Context 源码实现谈 React 性能优化

    (给前端大全加星标,提升前端技能) 转自:魔术师卡颂 学完这篇文章,你会收获: 了解Context的实现原理 源码层面掌握React组件的render时机,从而写出高性能的React组件 源码层面了解 ...

  8. React 性能优化完全指南,将自己这几年的心血总结成这篇!

    作者: MoonBall 原文地址: https://juejin.cn/post/6935584878071119885 本文分为三部分,首先介绍 React 的工作流,让读者对 React 组件更 ...

  9. React性能优化总结

    文章同步于Github Pines-Cheng/blog 初学者对React可能满怀期待,觉得React可能完爆其它一切框架,甚至不切实际地认为React可能连原生的渲染都能完爆--对框架的狂热确实会 ...

最新文章

  1. 使用 Blender* 重新拓扑 VR 和游戏素材
  2. python中文件读写位置的作用-Python中文件的读写
  3. Mybatis的select方法
  4. 编程方法学21:监听器和迭代器回顾
  5. python设置tk退出_退出tkinter gui
  6. Java枚举(用Java普通类模拟枚举的实现原理及JDK枚举API使用示例)
  7. python基础教程博客_python基础教程(十)
  8. function declaration isn't a prototype解决办法
  9. JavaSE基础——Map集合、 Collections(集合工具类)
  10. python if elif else_Python 基础起步 (九) 条件语句 if elif else 其实很简单
  11. 一次新业务接入联调及上线支持的出差经验小结
  12. Hutool使用总结(VIP典藏版)
  13. 真正彻底卸载ie8的某些加载项
  14. 认识中药(5)--胖大海
  15. 小升初数学知识体系梳理
  16. 【python实现视频解帧并保存到文件夹】
  17. 南方cass计算表面积_CASS-工程应用“计算表面积”
  18. 贪心算法 Greedy
  19. 上海宝山锦隆考试基地科目三笔记
  20. 基于sqlserver数据库的学生成绩管理系统

热门文章

  1. tp5循环查询语句_如何用Excel快速生成SQL语句,用过的人都说好
  2. oracle 加查询锁,oracle 锁查询 select加锁方法
  3. 为什么打印还要另存为_锦学考研 | 打印准考证的常犯错误
  4. python中列表生成式strip_Python 列表API 序列类型   列表生成
  5. dct变换的主要优点有哪些_网络拓扑结构有哪些类型 不同类型网络拓扑结构优缺点介绍【图文】...
  6. 线性回归损失函数为什么要用平方形式
  7. 【阿里云课程】神经网络:从生物学机制到全连接神经网络的局限性
  8. 【直播回放】60分钟了解各类图像和视频生成GAN结构
  9. 2022年跨境电商的风口还在吗?
  10. MySQL获取Schema表名和字段信息