从 MobX 4/5 迁移 {🚀}
MobX 6 与 MobX 5 有很大不同。此页面涵盖了从 MobX 4 和 5 迁移到 6 的指南,以及所有更改的详尽列表。
为了更好地理解,请查看 MobX 6.0 的 CHANGELOG。
⚠️ 警告:根据代码库的大小和复杂度、MobX 使用模式以及自动化测试的质量等因素,本迁移指南可能需要您花费 1 个小时到几天不等的时间。如果您不信任您的持续集成或 QA/测试流程来识别任何意外故障,请不要升级。意外行为变化可能是由 MobX 本身的更改或对 Babel/TypeScript 构建配置所需更改引起的。⚠️
入门
- 将
mobx
更新到 MobX 4/5 的最新版本,并解决任何弃用消息。 - 将
mobx
更新到版本 6。 - 如果您从 MobX 4 升级,并且需要在没有代理的情况下支持 Internet Explorer/React Native,请在应用程序初始化时调用
import { configure } from "mobx"; configure({ useProxies: "never" })
,以退回代理实现。有关更多详细信息,请查看 代理支持 部分。 - 对于 babel 用户
- 如果您使用 Babel 并启用了类属性,请禁用旧版宽松字段支持:
["@babel/plugin-proposal-class-properties", { "loose": false }]
- (可选)在 MobX 6 中,装饰器已成为可选的。如果您不再希望使用装饰器,请从您的 babel 配置和依赖项中删除
plugin-proposal-decorators
。有关更多详细信息,请查看 启用装饰器 {🚀} 部分。
- 如果您使用 Babel 并启用了类属性,请禁用旧版宽松字段支持:
- 对于 Typescript 用户
- 将标志
"useDefineForClassFields": true
添加到您的编译器配置中。 - (可选)在 MobX 6 中,装饰器已成为可选的。如果您不再希望使用装饰器,请从您的 TypeScript 配置中删除/禁用
experimentalDecorators
配置。有关更多详细信息,请查看 启用装饰器 {🚀} 部分。
- 将标志
- MobX 的默认配置已变得更加严格。我们建议在完成升级后采用新的默认值,请查看 配置 {🚀} 部分。在迁移期间,我们建议以与在 v4/v5 中开箱即用的相同方式配置 MobX:
import {configure} from "mobx"; configure({ enforceActions: "never" });
。在完成整个迁移过程并验证您的项目按预期工作后,考虑启用标志computedRequiresReaction
、reactionRequiresObservable
和observableRequiresReaction
以及enforceActions: "observed"
以编写更具特色的 MobX 代码。
makeObservable
将类升级以使用 由于 JavaScript 在构造类字段方面存在标准化限制,MobX 无法再通过装饰器或 decorate
实用程序来更改类字段的行为。相反,必须通过 constructor
使字段可观察。这可以通过三种不同的方式完成
- 删除所有装饰器,并在
constructor
中调用makeObservable
,并明确定义哪些字段应该使用哪个装饰器来使其可观察。例如:makeObservable(this, { count: observable, tick: action, elapsedTime: computed })
(注意,第二个参数对应于传递给decorate
的参数)。如果您希望在代码库中删除装饰器,并且项目还不算太大,那么这是推荐的方法。 - 保留所有装饰器,并在
constructor
中调用makeObservable(this)
。这将获取装饰器生成的元数据。如果您希望限制 MobX 6 迁移的影响,这是推荐的方法。 - 删除装饰器,并在类
constructor
中使用makeAutoObservable(this)
。
查看 makeObservable / makeAutoObservable 以获取更多详细信息。
一些需要注意的细节
- 需要在每个声明了基于 MobX 成员的类定义中使用
makeObservable
/makeAutoObservable
。因此,如果子类和超类都引入了可观察成员,那么它们都必须调用makeObservable
。 makeAutoObservable
将使用一个新的装饰器autoAction
来标记方法,该装饰器仅在不在派生上下文的情况下才应用action
。这使得从计算属性调用自动装饰的方法也变得安全。
迁移具有大量类的庞大代码库可能令人望而生畏。但不用担心,有一个代码模版可以自动完成上述过程!
mobx-undecorate
代码模版升级您的代码
使用 如果您是 MobX 的现有用户,那么您的代码使用了大量的装饰器,或等效的 decorate
调用。
mobx-undecorate
包提供了一个代码模版,可以自动更新您的代码以符合 MobX 6。您无需安装它;而是使用 npx
工具下载并执行它,如果您尚未安装,则需要安装。
要摆脱所有 MobX 装饰器的使用,并将它们替换为等效的 makeObservable
调用,请转到包含源代码的目录并运行
npx mobx-undecorate
MobX 将继续支持装饰器 - 因此,如果您想保留它们,并且只在需要的地方引入 makeObservable(this)
,可以使用 --keepDecorators
选项
npx mobx-undecorate --keepDecorators
查看 文档 以获取更多选项。
mobx-undecorate
的局限性
mobx-undecorate
命令必须在还没有构造函数的类中引入构造函数。如果构造函数的基类期望参数,则代码模版无法为要升级的子类引入这些参数,并且 super
调用也不会传递它们。您必须手动修复这些问题。该工具将在这些情况下生成 // TODO: [mobx-undecorate]
注释。
对于 React 类组件,我们有一个特殊情况,可以执行正确的事情,并将 props
传递给超类。
函数会自动转换
成为深度可观察结构一部分的函数会自动转换为 autoAction
或如果它是生成器函数,则转换为 flow
。有关详细信息,请查看 推断规则。这意味着原始函数引用不会保留 - 与原始数组/对象/集合/映射引用在转换为可观察对象时丢失的精神相同。这在某些情况下可能会令人惊讶。如果不需要此行为,请使用 observable.shallow
/ observable.ref
/ false
/ deep: flase
来阻止转换过程,或确保函数已经是 action
,如问题中所示。