MobX 🇺🇦

MobX 🇺🇦

  • API 参考
  • 中文
  • 한국어
  • 赞助商
  • GitHub

›微调

介绍

  • 关于 MobX
  • 关于这份文档
  • 安装
  • MobX 的精髓

MobX 核心

  • 可观察状态
  • 动作
  • 计算值
  • 反应 {🚀}
  • API

MobX 和 React

  • React 集成
  • React 优化 {🚀}

技巧 & 窍门

  • 定义数据存储
  • 理解响应性
  • 子类化
  • 分析响应性 {🚀}
  • 带参数的计算值 {🚀}
  • MobX-utils {🚀}
  • 自定义可观察对象 {🚀}
  • 延迟可观察对象 {🚀}
  • 集合实用程序 {🚀}
  • 拦截 & 观察 {🚀}

微调

  • 配置 {🚀}
  • 装饰器 {🚀}
  • 从 MobX 4/5 迁移 {🚀}
编辑

配置 {🚀}

MobX 根据您使用它的方式、要定位的 JavaScript 引擎以及是否希望 MobX 提示最佳实践,提供了几种配置。大多数配置选项可以使用 configure 方法设置。

代理支持

默认情况下,MobX 使用代理来使数组和普通对象可观察。代理提供了最佳性能和跨环境的一致性行为。但是,如果您要定位不支持代理的环境,则必须禁用代理支持。最值得注意的是,当您定位 Internet Explorer 或不使用 Hermes 引擎的 React Native 时,情况就是这样。

可以使用 configure 禁用代理支持

import { configure } from "mobx"

configure({
    useProxies: "never"
})

useProxies 配置的接受值为

  • "always" (默认): MobX 预计只在具有 Proxy 支持 的环境中运行,如果不存在这样的环境,它将报错。
  • "never": 不使用代理,MobX 回退到非代理替代方案。这与所有 ES5 环境兼容,但会导致各种 限制。
  • "ifavailable" (实验性): 如果代理可用,则使用代理,否则 MobX 回退到非代理替代方案。这种模式的优点是,MobX 会尝试在使用 ES5 环境中无法使用的 API 或语言特性时发出警告,从而在现代环境中遇到 ES5 限制时触发错误。

注意: 在 MobX 6 之前,必须选择 MobX 4 用于旧引擎,或 MobX 5 用于新引擎。但是,MobX 6 支持两者,尽管在定位旧 JavaScript 引擎时需要为某些 API(如 Map)提供垫片。代理无法垫片化。即使存在垫片,它们也不支持完整的规范,不适合 MobX。不要使用它们。

没有代理支持的限制

  1. 可观察数组不是真正的数组,因此它们不会通过 Array.isArray() 检查。实际结果是,您通常需要先 .slice() 数组(获取真实数组的浅拷贝),然后才能将其传递给第三方库。例如,连接可观察数组不会按预期工作,因此请先 .slice() 它们。
  2. 在创建后添加或删除现有可观察普通对象的属性不会自动被拾取。如果您打算将对象用作基于索引的查找映射,换句话说,用作事物的动态集合,请使用可观察映射。

即使在没有启用代理的情况下,也可以动态地向对象添加属性并检测它们的添加。这可以通过使用 集合实用程序 {🚀} 来实现。确保使用 set 实用程序设置(新)属性,并使用 values / keys 或 entries 实用程序中的一个来迭代对象,而不是使用内置的 JavaScript 机制。但是,由于这很容易忘记,我们建议尽可能使用可观察映射。

装饰器支持

有关启用实验性装饰器支持,请查看 启用装饰器 {🚀} 部分。

代码风格检查选项

为了帮助您采用 MobX 提倡的模式,严格区分动作、状态和派生,MobX 可以通过提示代码风格问题来“代码风格检查” 您的编码模式。为了确保 MobX 尽可能严格,请采用以下设置,并阅读对它们的解释

import { configure } from "mobx"

configure({
    enforceActions: "always",
    computedRequiresReaction: true,
    reactionRequiresObservable: true,
    observableRequiresReaction: true,
    disableErrorBoundaries: true
})

在某些时候,您会发现这种严格程度可能很烦人。一旦您确定自己(和您的同事)理解了 MobX 的心理模型,就可以禁用这些规则以提高效率。

此外,有时您会遇到必须抑制这些规则触发的警告的情况(例如,通过包装在 runInAction 中)。这很好,这些建议有一些好的例外情况。不要对它们教条主义。

请务必尝试我们的 eslint 插件。虽然有些问题可以静态地发现,但另一些问题只能在运行时检测到。该插件旨在补充这些规则,而不是替代它们。自动修复功能也可以帮助您处理样板代码。

enforceActions

enforceActions 的目标是让您不要忘记将事件处理程序包装在 action 中。

可能的选项

  • "observed" (默认): 所有在某处被观察到的状态都需要通过动作来更改。这是默认值,也是非平凡应用程序中推荐的严格模式。
  • "never": 状态可以在任何地方更改。
  • "always": 状态始终需要通过动作来更改,实际上这也包括创建。

"observed" 的好处是它允许您在动作之外创建可观察对象并自由地修改它们,只要它们尚未在任何地方使用。

由于原则上状态始终应该从某些事件处理程序创建,而事件处理程序应该被包装,因此 "always" 最好地捕获了这一点。但是,您可能不希望在单元测试中使用这种模式。

在您懒惰地创建可观察对象(例如在计算属性中)的罕见情况下,您可以使用 runInAction 将创建临时地包装在动作中。

computedRequiresReaction: boolean

禁止从动作或反应之外直接访问任何未观察到的计算值。这保证您不会以 MobX 不会缓存它们的方式使用计算值。默认值: false。

在以下示例中,MobX 不会在第一个代码块中缓存计算值,但在第二个和第三个代码块中会缓存结果

class Clock {
    seconds = 0

    get milliseconds() {
        console.log("computing")
        return this.seconds * 1000
    }

    constructor() {
        makeAutoObservable(this)
    }
}

const clock = new Clock()
{
    // This would compute twice, but is warned against by this flag.
    console.log(clock.milliseconds)
    console.log(clock.milliseconds)
}
{
    runInAction(() => {
        // Will compute only once.
        console.log(clock.milliseconds)
        console.log(clock.milliseconds)
    })
}
{
    autorun(() => {
        // Will compute only once.
        console.log(clock.milliseconds)
        console.log(clock.milliseconds)
    })
}

observableRequiresReaction: boolean

警告任何未观察到的可观察访问。如果您想检查是否在没有“MobX 上下文”的情况下使用可观察对象,请使用此选项。这是查找任何缺少的 observer 包装器(例如在 React 组件中)的好方法。但它也会找到缺少的动作。默认值: false

configure({ observableRequiresReaction: true })

注意: 在用 observer 包装的组件上使用 propTypes 可能会为此规则触发误报。

reactionRequiresObservable: boolean

当在没有访问任何可观察对象的情况下创建反应(例如 autorun)时发出警告。使用此选项来检查是否不必要地用 observer 包装 React 组件,用 action 包装函数,或者查找您只是忘记使某些数据结构或属性可观察的情况。默认值: false

configure({ reactionRequiresObservable: true })

disableErrorBoundaries: boolean

默认情况下,MobX 会捕获并重新抛出您的代码中发生的异常,以确保一个异常中的反应不会阻止其他可能无关的反应的计划执行。这意味着异常不会传播回导致异常的原始代码,因此您无法使用 try/catch 捕获它们。

通过禁用错误边界,异常可以逃逸派生。这可能会简化调试,但可能会使 MobX 以及扩展到您的应用程序处于不可恢复的损坏状态。 默认值:false。

此选项非常适合单元测试,但请记住在每次测试后调用 _resetGlobalState,例如通过在 jest 中使用 afterEach,例如

import { _resetGlobalState, observable, autorun, configure } from "mobx"

configure({ disableErrorBoundaries: true })

test("Throw if age is negative", () => {
    expect(() => {
        const age = observable.box(10)
        autorun(() => {
            if (age.get() < 0) throw new Error("Age should not be negative")
        })
        age.set(-1)
    }).toThrow("Age should not be negative")
})

afterEach(() => {
    _resetGlobalState()
})

safeDescriptors: boolean

MobX 使某些字段 不可配置 或 不可写,以防止您执行不支持的操作或可能破坏您的代码的操作。但是,这也会阻止您在测试中进行 监视/模拟/存根。configure({ safeDescriptors: false }) 禁用此安全措施,使所有内容都 可配置 和 可写。请注意,它不会影响现有的可观察对象,只影响之后创建的可观察对象。 谨慎使用 并且仅在需要时使用 - 不要为所有测试全局关闭它,否则您可能会遇到误报(通过包含错误代码的测试)。 默认值:true

configure({ safeDescriptors: false })

其他配置选项

isolateGlobalState: boolean

当在同一个环境中有多个 MobX 实例处于活动状态时,隔离 MobX 的全局状态。当您有一个使用 MobX 的封装库,与使用 MobX 的应用程序位于同一个页面时,这很有用。当您从库中调用 configure({ isolateGlobalState: true }) 时,库内部的反应性将保持自包含。

没有此选项,如果多个 MobX 实例处于活动状态,它们的内部状态将被共享。这样做的好处是,来自两个实例的可观察对象可以协同工作,缺点是 MobX 版本必须匹配。 默认值:false

configure({ isolateGlobalState: true })

reactionScheduler: (f: () => void) => void

设置一个新的函数来执行所有 MobX 反应。默认情况下,reactionScheduler 只运行 f 反应,没有任何其他行为。这对于基本调试或减慢反应速度以可视化应用程序更新很有用。 默认值:f => f()

configure({
    reactionScheduler: (f): void => {
        console.log("Running an event after a delay:", f)
        setTimeout(f, 100)
    }
})
← 拦截 & 观察 {🚀}装饰器 {🚀} →
  • 代理支持
    • 没有代理支持的限制
  • 装饰器支持
  • Lint 选项
  • 其他配置选项
MobX 🇺🇦
文档
关于 MobXMobX 的核心
社区
GitHub 讨论 (NEW)Stack Overflow
更多
Star