MobX 🇺🇦

MobX 🇺🇦

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

›技巧与窍门

简介

  • 关于 MobX
  • 关于本文档
  • 安装
  • MobX 的精髓

MobX 核心

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

MobX 和 React

  • React 集成
  • React 优化 {🚀}

技巧与窍门

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

微调

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

带参数的计算属性 {🚀}

computed 注解只能用于没有参数的 getter。那么带参数的计算属性呢?考虑下面的 React 组件示例,它渲染了一个特定的 Item,并且应用程序支持多选。

我们如何实现像 store.isSelected(item.id) 这样的派生?

import * as React from 'react'
import { observer } from 'mobx-react-lite'

const Item = observer(({ item, store }) => (
    <div className={store.isSelected(item.id) ? "selected" : ""}>
        {item.title}
    </div>
))

我们可以通过四种方式来解决这个问题。你可以在 这个 CodeSandbox 中尝试下面的解决方案。

1. 派生不需要是 computed

一个函数不需要被标记为 computed,MobX 就可以跟踪它。上面的示例就可以正常工作。重要的是要意识到,计算属性只是缓存点。如果派生函数是纯函数(并且它们应该如此),那么使用或不使用 computed 标记 getter 或函数不会改变行为,只是效率略低。

上面的示例虽然 isSelected 不是 computed,但依然可以正常工作。observer 组件会检测和订阅 isSelected 读取的任何可观察对象,因为该函数是在渲染过程中执行的,而渲染是被跟踪的。

值得注意的是,在这个例子中,所有 Item 组件都会对未来的选择更改做出响应,因为它们都直接订阅了捕获选择的可观察对象。这是一个最坏情况的示例。通常情况下,拥有未标记的派生函数是完全可以的,并且这是一个很好的默认策略,直到数字证明需要做其他事情。

2. 封闭参数

与原始实现相比,这是一个更高效的实现。

import * as React from 'react'
import { computed } from 'mobx'
import { observer } from 'mobx-react-lite'

const Item = observer(({ item, store }) => {
    const isSelected = computed(() => store.isSelected(item.id)).get()
    return (
        <div className={isSelected ? "selected" : ""}>
            {item.title}
        </div>
    )
})

我们在一个反应的中间创建一个新的计算属性。这可以正常工作,并且确实引入了额外的缓存点,避免了所有组件都必须直接对每个选择更改做出响应。这种方法的优点是,组件本身只有在 isSelected 状态切换时才会重新渲染,在这种情况下,我们确实需要重新渲染来切换 className。

我们在下一次渲染中创建一个新的 computed 是可以的,这个新的 computed 现在将成为缓存点,而之前的 computed 将被很好地清理。这是一个很棒且高级的优化技巧。

3. 移动状态

在这个特定情况下,选择也可以存储为 Item 上的 isSelected 可观察对象。然后,存储中的选择可以表示为 computed 而不是可观察对象:get selection() { return this.items.filter(item => item.isSelected) },我们不再需要 isSelected。

4. 使用 computedFn {🚀}

最后,来自 mobx-utils 的 computedFn 可用于 todoStore.selected 的定义中,以自动记忆 isSelected。它创建一个函数,该函数为每组输入参数记忆输出。

我们建议不要太快使用这种方法。记忆通常需要考虑函数将被调用多少次,以及使用多少个不同的参数,才能推断出内存消耗。但是,如果函数的结果没有被任何反应观察到,它会自动清理条目,因此在正常情况下不会导致内存泄漏。

再次,请查看 链接的 CodeSandbox 以尝试使用此方法。

← 分析反应性 {🚀}MobX-utils {🚀} →
  • 1. 派生不需要是 computed
  • 2. 封闭参数
  • 3. 移动状态
  • 4. 使用 computedFn {🚀}
MobX 🇺🇦
文档
关于 MobXMobX 的精髓
社区
GitHub 讨论 (NEW)Stack Overflow
更多
点赞