首页 文章 精选 留言 我的

精选列表

搜索[前端构建],共10000篇文章
优秀的个人博客,低调大师

React新Context API在前端状态管理的实践

11/10号文档资料已全面更新!;《【阿里P7】Android高级教程+BAT面试题》,可复制链接后用石墨文档 App 或小程序打开:【阿里P7】移动互联网架构师进阶高级教程+BAT面试题众所周知,React的单向数据流模式导致状态只能一级一级的由父组件传递到子组件,在大中型应用中较为繁琐不好管理,通常我们需要使用Redux来帮助我们进行管理,然而随着React 16.3的发布,新context api成为了新的选择。 一、Redux的简介以及缺陷 Redux来源于Flux并借鉴了Elm的思想,主要原理如下图所示: 可以看到,Redux的数据流其实非常简单,外部事件通过actionCreator函数调用dipsatch发布action到reducers中,然后各自的reducer根据action的类型(action.type) 来按需更新整个应用的state。 redux设计有以下几个要点: 1. state是单例模式且不可变的,单例模式避免了不同store之间的数据交换的复杂性,而不可变数据提供了十分快捷的撤销重做、“时光旅行”等功能。 2. state只能通过reducer来更新,不可以直接修改。 3. reducer必须是纯函数,形如(state,action) => newState redux本身是个非常纯粹的状态管理库,需要通过react-redux这个库的帮助来管理react的状态。react-redux主要包含两个部分。 1. Provider组件:可以将store注入到子组件的cotext中,所以一般放在应用的最顶层。 2. connect函数: 返回一个高阶函数,把context中由Provider注入的store取出来然后通过props传递到子组件中,这样子组件就能顺利获取到store了。 虽然redux在React项目中得到了普遍的认可与使用率,然而在现实项目中redux还是存在着很多缺点: 1.样板代码过多:增加一个action往往需要同时定义相应的actionType然后再写N个相关的reducer。例如当添加一个异步加载事件时,需要同时定义加载中、加载失败以及加载完成三个actionType,需要一个相对应的reducer通过switch分支来处理对应的actionType,冗余代码过多。 2.更新效率问题:由于使用不可变数据模式,每次更新state都需要拷贝一份完整的state造成了内存的浪费以及性能的损耗。 3.数据传递效率问题:由于react-redux采用的旧版context API,context的传递存在着效率问题。 其中,第一个问题目前已经存在着非常多的解决方案,诸如dva、rematch以及mirror等等,笔者也造过一个类似的轮子restated这里不做过多阐述。 第二个问题首先redux以及react-redux中已经做了非常详尽的优化了,其次擅用shouldComponentUpdate方法也可以避免很多不必要的更新,最后,也可以使用一些不可变数据结构如immutable、Immr等来从根本上解决拷贝开销问题。 第三个问题属于React自身API的局限,从第三方库的角度上来说,能做的很有限。 二、Context API context API主要用来解决跨组件传参泛滥的问题(prop drilling),旧的context API的语法形式如下: 可以看到,使用context api可以把DeliverComponent中的参数color直接跨越MidComponent传递到ReceiverComponent中,不需要冗余的使用props参数传递,特别是ReceiverComponent层级特别深的时候,使用context api能够很大程度上节省重复代码避免bug。 旧Context API的缺陷 旧的context api主要存在如下的缺陷: 1.代码冗余:提供context的组件要定义childContextTypes与getChildContext才能把context传下去。同时接收context的也要先定义contextTypes才能正确拿到数据。 2.传递效率:虽然功能上context可以跨层级传递,但是本质上context也是同props一样一层一层的往下传递的,当层级过深的时候还是会出现效率问题。 3.shouldComponentUpdate:由于context的传递也是一层一层传递,因此它也会受到shouldComponent的阻断。换句话说,当传递组件的context变化时,如果其下面某一个中间组件的shouldComponentUpdate方法返回false,那么之后的接收组件将不会受到任何context变化。 为了解决旧版本的shouldComponentUpdate问题,保证所有的组件都能收到store的变化,react-redux只能传递一个getState方法给各个组件用于获取最新的state(直接传递state可能会被阻断,后面的组件将接收不到state的变化),然后每个connect组件都需要直接或间接监听state的变化,当state发生改变时,通过内部notifyNestedSubs方法从上往下依次触发各个子组件通过getState方法获取最新的state更新视图。这种方式效率较低而且比较hack。 三、新Context API React自16.3开始提供了一个新的context api,彻底解决了旧Context API存在的种种问题。 下面是新context api(右)与使用旧context api的react-redux(左)数据流的比较: 可以看到,新的context api可以直接将context数据传递到传递到子组件中而不需要像旧context api那样级联传递。因此也可以突破shouldComponentUpdate的限制。新版的context api的定义如下: 下面是一个比较简单的应用示例: 可以看到新的context api主要包含一个Provider和Consumer对,在Provider输入的数据可以在Consumer中获得。 新context api的要点如下: 1. Provider和 Consumer必须来自同一次 React.createContext调用。也就是说 NameContext.Provider和 AgeContext.Consumer是无法搭配使用的。 2. React.createContext方法接收一个默认值作为参数。当 Consumer外层没有对应的 Provider时就会使用该默认值。 3. Provider 组件的 valueprop 值发生变更时,其内部组件树中对应的 Consumer组件会接收到新值并重新执行 children函数。此过程不受 shouldComponentUpdete 方法的影响。 4. Provider组件利用 Object.is 检测 value prop 的值是否有更新。注意 Object.is和 === 的行为不完全相同。 5. Consumer组件接收一个函数作为 children prop 并利用该函数的返回值生成组件树的模式被称为 Render Props 模式。 四、新Context API的应用 新的Context API大大简化了react状态传递的问题,也出现了一些基于它的状态管理库,诸如:unstated、react-waterfall等等。下面我们主要尝试使用新context api来造一个react-redux的轮子。 1. Provider 由于新的context api传递过程中不会被shouldComponentUpdate阻断,所以我们只需要在Provider里面监听store变化即可: 2. connect 相比较于react-redux,connect中的高阶组件逻辑就简单的多,不需要监听store变化,直接获得Provider传入的state然后再传递给子组件即可: 好了,至此整个React-redux的接口和功能都已经基本cover了,下面继续介绍一些比较重要的性能优化。 3. 性能优化 - 减少重复渲染 性能优化最大的一部分就是要减少无意义的重复渲染,当WrappedComponent的参数值没有变化时我们应该阻止其重新渲染。可以通过手写shouldComponentUpdate方法实现,也可以直接通过PureComponent组件来达到我们的目标: 这里需要注意的是,本示例的mapDispatchToProps未支持ownProps参数,因此可以把它的返回值看成是不变的,否则每次调用它返回的action函数都是新创建的,从而导致Prevent接收到的参数始终是不同的,达不到预期效果。更为复杂的情况请参考react-redux源码中selector相关的部分。 4. 性能优化 - 减少层级嵌套 性能优化另一个要点就是减少组件的层级嵌套,新context api在获取context值的时候需要嵌套一层Consumer组件,这也是其比旧context api劣势的地方。除此之外,我们应该尽量减少层级的嵌套。因此在前一个性能优化中我们不应该再次嵌套一个PureComponent,取而代之的是,我们可以直接在Cunsumer中实现一个memory机制,实现代码如下: 下面是前后chrome开发人员工具中组件层级的对比,可以看到嵌套层级成功减少了一层,两层嵌套是新context api的局限,如果要保持react-redux的接口模式则无法再精简了。 原文链接https://www.toutiao.com/i6615135777976222216/ 最后 我们今年整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。 主要包括腾讯,以及字节跳动,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。 以下为我整理的资料免费分享;【阿里P7】Android高级教程+BAT面试题 1.Android高级技术脑图 2.P7级Android高级架构视频教程 3.Android核心高级技术PDF文档+BAT大厂面试真题解析 4.Android思维脑图(技能树) 1.Android高级技术脑图; 查漏补缺,体系化深入学习提升 2.【Android高级架构视频教程】; 全套部分展示; java与Android内核进阶专题视频与源码 阿里P7级全套高级学习视频; 3.Android核心高级技术PDF文档,BAT大厂面试真题解析 4.Android思维脑图(技能树) 免费分享 【阿里P7】移动互联网架构师进阶高级教程+BAT面试题 为什么免费分享? 我的目的是让更多需要的Android开发朋友能够提升自己的技术水平无论是Android,还是qq,微信,360等,想在互联网上最大程度推广,就必须免费!如果我的学习资料对你有帮助,点个赞,谢谢!

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册