MobX 🇺🇦

MobX 🇺🇦

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

›微调

介绍

  • 关于 MobX
  • 关于这份文档
  • 安装
  • MobX 的要点

MobX 核心

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

MobX 和 React

  • React 集成
  • React 优化 {🚀}

技巧与窍门

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

微调

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

装饰器

启用装饰器

经过多年的修改,ES 装饰器终于在 TC39 进程中达到了第 3 阶段,这意味着它们非常稳定,并且不会像之前的装饰器提案那样再次发生重大变化。MobX 已经实现了对这种新的“2022.3/第 3 阶段”装饰器语法的支持。使用现代装饰器,不再需要调用 `makeObservable` / `makeAutoObservable`。

2022.3 装饰器在以下方面得到支持

  • TypeScript(5.0 及更高版本,确保 `experimentalDecorators` 标志未启用)。示例提交。
  • 对于 Babel,请确保插件 proposal-decorators 启用并使用最高版本(目前为 `2023-05`)。示例提交。
// tsconfig.json
{
    "compilerOptions": {
        "experimentalDecorators": false /* or just remove the flag */
    }
}

// babel.config.json (or equivalent)
{
    "plugins": [
        [
            "@babel/plugin-proposal-decorators",
            {
                "version": "2023-05"
            }
        ]
    ]
}

使用装饰器

import { observable, computed, action } from "mobx"

class Todo {
    id = Math.random()
    @observable accessor title = ""
    @observable accessor finished = false

    @action
    toggle() {
        this.finished = !this.finished
    }
}

class TodoList {
    @observable accessor todos = []

    @computed
    get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length
    }
}

请注意在使用 `@observable` 时使用新的 `accessor` 关键字。它是 2022.3 规范的一部分,如果您想使用现代装饰器,则需要它。

使用传统装饰器

我们不建议代码库使用 TypeScript / Babel 传统装饰器,因为它们永远不会成为语言的正式部分,但您仍然可以使用它们。这需要对转译进行特定的设置。

MobX 在 6.0 版本之前鼓励使用传统装饰器,并将事物标记为 `observable`、`computed` 和 `action`。虽然 MobX 6 建议不要使用这些装饰器(而是使用现代装饰器或 makeObservable / makeAutoObservable),但在当前主版本中仍然可以使用。在 MobX 7 中将删除对传统装饰器的支持。

import { makeObservable, observable, computed, action } from "mobx"

class Todo {
    id = Math.random()
    @observable title = ""
    @observable finished = false

    constructor() {
        makeObservable(this)
    }

    @action
    toggle() {
        this.finished = !this.finished
    }
}

class TodoList {
    @observable todos = []

    @computed
    get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length
    }

    constructor() {
        makeObservable(this)
    }
}

从传统装饰器迁移

要从传统装饰器迁移到现代装饰器,请执行以下步骤。

  1. 禁用/删除 TypeScript 配置(或 Babel 等效项)中的 `experimentalDecorators` 标志。
  2. 从使用装饰器的类构造函数中删除所有 `makeObservable(this)` 调用。
  3. 将所有 `@observable`(及其变体)的实例替换为 `@observable accessor`。

装饰器更改/注意事项

MobX 的 2022.3 装饰器与 MobX 5 装饰器非常相似,因此用法基本相同,但有一些注意事项。

  • `@observable accessor` 装饰器不可枚举。`accessor` 在过去没有直接等效项 - 它们是语言中的一个新概念。我们选择将它们设为不可枚举的、非自身属性,以便更好地遵循 ES 语言的精神以及 `accessor` 的含义。枚举性的主要案例似乎围绕序列化和剩余解构。
    • 关于序列化,隐式序列化所有属性可能在 OOP 世界中并不理想,因此这似乎不是一个重大问题(考虑实现 `toJSON` 或使用 `serializr` 作为可能的替代方案)。
    • 解决剩余解构问题,这种方法在 MobX 中是一种反模式 - 这样做会(可能不必要地)触及所有可观察对象并使观察者过度反应)。
  • `@action some_field = () => {}` 过去和现在都是有效的用法。但是,传统装饰器和现代装饰器之间的继承有所不同。
    • 在传统装饰器中,如果超类有一个用 `@action` 装饰的字段,子类试图覆盖同一个字段,它将抛出 `TypeError: Cannot redefine property` 错误。
    • 在现代装饰器中,如果超类有一个用 `@action` 装饰的字段,子类试图覆盖同一个字段,则允许覆盖该字段。但是,子类上的字段不是动作,除非它也在子类声明中用 `@action` 装饰。

使用 `observer` 作为装饰器

来自 `mobx-react` 的 `observer` 函数既是函数,也是装饰器,可用于类组件。

@observer
class Timer extends React.Component {
    /* ... */
}
← 配置 {🚀}从 MobX 4/5 迁移 {🚀} →
  • 启用装饰器
  • 使用装饰器
  • 使用 `observer` 作为装饰器
MobX 🇺🇦
文档
关于 MobXMobX 的要点
社区
GitHub 讨论(新)Stack Overflow
更多
点赞