双辽做网站,苏州企业网站建设定制,网站建设报价选兴田德润,网站开发与维护是学什么1 引言 setState 是 React 框架最常用的命令#xff0c;它是用来更新状态的#xff0c;这也是 React 框架划时代的功能。 但是 setState 函数是 react 包导出的#xff0c;他们又是如何与 react-dom react-native react-art 这些包结合的呢#xff1f; 通过 how-does-setst…1 引言 setState 是 React 框架最常用的命令它是用来更新状态的这也是 React 框架划时代的功能。 但是 setState 函数是 react 包导出的他们又是如何与 react-dom react-native react-art 这些包结合的呢 通过 how-does-setstate-know-what-to-do 这篇文章可以解开这个秘密。 2 概述 setState 函数是在 React.Component 组件中调用的所以最自然的联想是更新 DOM 的逻辑在 react 包中实现。 但是 react 却可以和 react-dom react-native react-art 这些包打配合甚至与 react-dom/server 配合在服务端运行那可以肯定 react 包中不含有 DOM 更新逻辑。 所以可以推断平台相关的 UI 更新逻辑分布在平台相关的包里react 包只做了代理。 React 引擎不在 react 包里 从 react 0.14 版本之后引擎代码就从 react 包中抽离了react 包仅仅做通用接口抽象。 也就是说react 包定义了标准的状态驱动模型的 API而 react-dom react-native react-art 这些包是在各自平台的具体实现。 各平台具体的渲染引擎实现被称为 reconciler通过这个链接可以看到 react-dom react-native react-art 这三个包的 reconciler 实现。 这说明了 react 包仅告诉你 React 拥有哪些语法而并不关心如何实现他们所以我们需要结合 react 包与 react-xxx 一起使用。 对于 contextreact 包仅仅会做如下定义
// A bit simplified
function createContext(defaultValue) {let context {_currentValue: defaultValue,Provider: null,Consumer: null};context.Provider {$$typeof: Symbol.for(react.provider),_context: context};context.Consumer {$$typeof: Symbol.for(react.context),_context: context};return context;
} 具体用到时由 react-dom 和 react-native 决定用何种方式实现 MyContext.Provider 这个 API。 这也说明了如果你不同步升级 react 与 react-dom 版本的话就可能碰到这样的报错fail saying these types are invalid原因是 API 定义与实现不匹配。 setState 怎么调用平台实现 每个平台对 UI 更新逻辑的实现会封装在 updater 函数里所以不同平台代码会为组件添加各自的 updater 实现
// Inside React DOM
const inst new YourComponent();
inst.props props;
inst.updater ReactDOMUpdater;// Inside React DOM Server
const inst new YourComponent();
inst.props props;
inst.updater ReactDOMServerUpdater;// Inside React Native
const inst new YourComponent();
inst.props props;
inst.updater ReactNativeUpdater; 不同于 props, updater 无法被直接调用因为这个 API 是由 react 引擎在 setState 时调用的
// A bit simplified
setState(partialState, callback) {// Use the updater field to talk back to the renderer!this.updater.enqueueSetState(this, partialState, callback);
} 关系可以这么描述react - setState - updater - react-dom 等。 Hooks Hooks 的原理与 setState 类似当调用 useState 或 useEffect 时其内部调用如下
// In React (simplified a bit)
const React {// Real property is hidden a bit deeper, see if you can find it!__currentDispatcher: null,useState(initialState) {return React.__currentDispatcher.useState(initialState);},useEffect(initialState) {return React.__currentDispatcher.useEffect(initialState);}// ...
}; ReactDOM 提供了 __currentDispatcher简化的说法:
// In React DOM
const prevDispatcher React.__currentDispatcher;
React.__currentDispatcher ReactDOMDispatcher;
let result;
try {result YourComponent(props);
} finally {// Restore it backReact.__currentDispatcher prevDispatcher;
} 可以看到Hooks 的原理与 setState 基本一致但需要注意 react 与 react-dom 之间传递了 dispatch虽然你看不到。但这个 dispatch 必须对应到唯一的 React 实例这就是为什么 Hooks 不允许同时加载多个 React 实例的原因。 和 updater 一样dispatch 也可以被各平台实现重写比如 react-debug-hooks 就重写了 dispatcher。 由于需要同时实现 readContext, useCallback, useContext, useEffect, useImperativeMethods, useLayoutEffect, useMemo, useReducer, useRef, useState工程量比较浩大建议了解基本架构就足够了除非你要深入参与 React 生态建设。 3 精读 与其他 React 分析文章不同本文并没有过于刨根问题的上来就剖析 reconciler 实现而是问了一个最基本的疑问为什么 setState 来自 react 包但实现却在 react-dom 里React 是如何实现这个 magic 的 通过这个疑问我们了解了 React 更上层的抽象能力如何用一个包制定规范用 N 包去实现它。 接口的力量 在日常编程中接口也拥有的强大力量下面举几个例子。 UI 组件跨三端的接口 由于 RN、Weex、Flux 的某些不足越来越多的人选择 “一个思想三端实现” 的方式做跨三端的 UI 组件这样既兼顾了性能又可以照顾到平台差异性对不同平台组件细节做定制优化。 要实施这个方案最大问题就是接口约定。一定要保证三套实现遵循同一套 API 接口业务代码才可以实现 “针对任意一个平台编写自动移植到其他平台”。 比较常用的做法是通过一套统一的 API 文件约束固定组件的输入输出不同平台的组件做平台具体实现。这个思想和 React 如出一辙。 当然 RN 这些框架本身也是同一接口在不同平台实现的典型只是做的不够彻底JS 与 Native 的通信导致了性能不如源生。 通用数据查询服务 通用数据查询服务也比较流行通过磨平各数据库语法让用户通过一套 SQL 查询各种类型数据库的数据。 这个方案中一套通用的查询语法就类似 React 定义的 API执行阶段会转化为各数据库平台的 SQL 方言。 小程序融合方案 现在这种方案很火。通过基于 template 或者 jsx 的语法一键发布到各平台小程序应用。 这种方案一定会抽象一套通用语法甚至几乎等价与 react 与 react-dom 的关系所有符合规范的语法转化为各小程序平台的实现。 4 总结 这种分平台实现方案与跨平台方案还是有很大区别的像 JAVA 虚拟机本质还是一套实现方案。而分平台的实现可以带来最原生的性能与体验同样收到的约束也最大应该其 API 应该是所有平台支持的一个子集。 另外这种方案不仅可以用于 一套规范不同平台的实现甚至可以用在 “同一平台的实现”。 无论是公司还是开源节界都有许多重复的轮子或者平台如果通过技术委员会约定一套平台的实现规范大家都遵循这个规范开发平台那未来就比较好做收敛或者说收敛的第一步都是先统一 API 规范。 留下一个思考题还有没有利用 setState 规范与实现分离的思想案例欢迎留下你的答案。 讨论地址是精读《setState 做了什么》 · Issue #122 · dt-fe/weekly 如果你想参与讨论请点击这里每周都有新的主题周末或周一发布。前端精读 - 帮你筛选靠谱的内容。 来源https://segmentfault.com/a/1190000017787272 转载于:https://www.cnblogs.com/lalalagq/p/10241717.html