夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 核心概念

  • 高级指引

  • Hook

  • 案例演示

  • Router

  • Redux

  • Jotai

  • Mobx

    • Mobx
    • observable state
    • actions
      • 使用 action 包装函数
      • action 绑定
      • 临时执行的 action
      • 异步执行 action
      • async / await 的替代方案
        • 使用 flow 进行替代
        • flow.bound
    • computeds
    • reactions
  • 其他

  • 《React》笔记
  • Mobx
夜猫子
2023-09-04
目录

actions

# 状态更改

使用 action 注解来修改 state 状态。

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

class Doubler {
    value = 0

    constructor(value) {
        makeObservable(this, {
            value: observable,
            increment: action.bound
        })
    }

   set increment() {
        this.value++
        this.value++
    }
}

const doubler = new Doubler()

// 这样调用 increment 是安全的, 因为它已经被绑定了。
setInterval(doubler.increment, 1000)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 使用 action 包装函数

  • action 不仅仅是一个注解,更是一个高阶函数,因此一切涉及修改 state 的操作,都应该将其标记为 action。
  • action 不会触发 state 的追踪。

示例:

const ResetButton = ({ formState }) => (
    <button
        onClick={action(e => {
            formState.resetPendingUploads()
            formState.resetValues()
            e.stopPropagation()
        })}
    >
        Reset form
    </button>
)
1
2
3
4
5
6
7
8
9
10
11

# action 绑定

为了解决 this 的指向问题,可以使用 action.bound 使 this 始终正确的绑定在函数内部。

(使用 makeAutoObservable(o, {}, { autoBind: true }) 会自动绑定所有的 actions 和 flows)

import { makeAutoObservable } from "mobx"

class Doubler {
    value = 0

    constructor(value) {
        makeAutoObservable(this, {}, { autoBind: true })
    }

    increment() {
        this.value++
        this.value++
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 临时执行的 action

可以使用 runInAction(fn) 来立即执行一个临时定义的 action。这在异步进程中非常有用。

import { observable, runInAction } from "mobx"

const state = observable({ value: 0 })

const getValue=()=>{
    return new Promise((resolve)=>{
        setTimeout(()=>{
            resolve(10)
        },1000)
    })    
}

runInAction(async() => {
  const data=await getValue()
  state=data
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 异步执行 action

任何的 state 的更改操作都应该处于 action 作用域中,因此,当处理 Promise 时,涉及 state 修改的操作都应当标识为action。

import { action, makeAutoObservable } from "mobx"

class Store {
    githubProjects = []
    state = "pending" // "pending", "done" or "error"

    constructor() {
        makeAutoObservable(this)
    }

    fetchProjects() {
        this.githubProjects = []
        this.state = "pending"
        fetchGithubProjectsSomehow().then(
            action("fetchSuccess", projects => {
                const filteredProjects = somePreprocessing(projects)
                this.githubProjects = filteredProjects
                this.state = "done"
            }),
            action("fetchError", error => {
                this.state = "error"
            })
        )
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# async / await 的替代方案

async / await 作为现代 js 中常用的异步方案,在 mobx 中不推荐使用,而是推荐 flow 作为替代。

Why? 因为 async / await 的本质是 promise 的包装,如上面的 fetchProjects,就是把await后的代码放到Promise.then()函数里,把catch部分的代码放到.catch的回调函数里,还是同样需要将异步的执行部分用 action 来包装起来,说白了,其本质还是一个 Promise 任务

# 使用 flow 进行替代

实现:generator 迭代器

import { flow, makeAutoObservable, flowResult } from "mobx"

class Store {
    githubProjects = []
    state = "pending"

    constructor() {
        makeAutoObservable(this, {
            fetchProjects: flow
        })
    }

    // 注意星号, 这是一个 generator 函数!
    *fetchProjects() {
        this.githubProjects = []
        this.state = "pending"
        try {
            // Yield 代替 await.
            const projects = yield fetchGithubProjectsSomehow()
            const filteredProjects = somePreprocessing(projects)
            this.state = "done"
            this.githubProjects = filteredProjects
        } catch (error) {
            this.state = "error"
        }
    }
}

const store = new Store()
const projects = await flowResult(store.fetchProjects())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# flow.bound

用法与 action.bound 类似,使this 始终被正确绑定在函数内部。

编辑 (opens new window)
上次更新: 2024/12/19 17:25:54
observable state
computeds

← observable state computeds→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式