【React】MobX

概述

mobx 实现像 vue 一样声明式的修改数据,我们在项目中直接使用 mobx + mobx-react 。

mobxjs/mobx-react: React bindings for MobX (github.com)

https://zh.mobx.js.org/the-gist-of-mobx.html

  • state 数据

  • action 动作

  • derivation 派生

    • computed
    • observer 监听变化,包裹的 React 组件
    • autorun 监听变化,像 watch

computed 必须是纯函数。而 action 可以修改 state (如 arr.push) 。

computed 采用惰性求值,会缓存其输出,并且只有当其依赖的可观察对象被改变时才会重新计算。 它们在不被任何值观察时会被暂时停用。

shell 复制代码
npm install mobx-react mobx --save

使用

tsx 复制代码
import React, {FC, useEffect} from 'react';
import {action, makeAutoObservable, makeObservable, observable} from "mobx";
import {observer} from "mobx-react";

class Timer {
    secondsPassed = 0;

    constructor() {
        // 使该类的所有属性变成响应式(自动)
        // makeAutoObservable(this)
        // 使该类的所有属性变成响应式(手动)
        makeObservable(this, {
            secondsPassed: observable,
            increment: action,
            reset: action
        })
    }

    increment(count:number) {
        this.secondsPassed += count;
    }

    reset() {
        this.secondsPassed = 0;
    }
}

const myTimer = new Timer()

type PropsType = { timer: Timer }
const TimerView = observer((props: PropsType) => {
    const {timer} = props
    return <button onClick={() => timer.reset()}>
        seconds passed : {timer.secondsPassed}
    </button>
})

const BasicDemo: FC = () => {
    useEffect(() => {
        const id = setInterval(() => myTimer.increment(10), 1000);
        return () => clearInterval(id);
    }, []);
    return <div>
        <p>Basic Demo</p>
        <TimerView timer={myTimer}/>
    </div>
}

export default BasicDemo;

案例

index.tsx

tsx 复制代码
<TodoList store={store}/>

store.ts

ts 复制代码
import { nanoid } from 'nanoid'
import { makeObservable, observable, action, computed } from 'mobx'

// Todo class
export class ObservableTodoStore {
    id = ''
    task = ''
    completed = false

    constructor(task: string) {
        makeObservable(this, {
            id: observable,
            task: observable,
            completed: observable,
            rename: action,
            toggleCompleted: action
        })

        this.id = nanoid(5)
        this.task = task
    }

    rename(newName: string) {
        this.task = newName
    }

    toggleCompleted() {
        this.completed = !this.completed
    }
}

// TodoList class
export class ObservableTodoListStore {
    todos: ObservableTodoStore[] = []

    constructor() {
        makeObservable(this, {
            todos: observable,
            completedTodosCount: computed, // 计算
            addTodo: action,
            removeTodo: action
        })
    }

    // get(用于计算,不用于修改) 获取已经完成的 todos 数量
    get completedTodosCount() {
        return this.todos.filter(t => t.completed).length
    }

    addTodo(task: string) {
        const newTodo = new ObservableTodoStore(task)
        this.todos.push(newTodo) // 声明式,像 Vue
    }

    removeTodo(id: string) {
        const index = this.todos.findIndex(t => t.id === id)
        this.todos.splice(index, 1)
    }
}

const store = new ObservableTodoListStore()
export default store

TodoList.tsx

tsx 复制代码
//...
type PropsType = {
    store: ObservableTodoListStore
}
const TodoList: FC<PropsType> = observer((props: PropsType) => {});
//...
相关推荐
左夕18 分钟前
分不清apply,bind,call?看这篇文章就够了
前端·javascript
Zha0Zhun1 小时前
一个使用ViewBinding封装的Dialog
前端
兆子龙1 小时前
从微信小程序 data-id 到 React 列表性能优化:少用闭包,多用 data-*
前端
滕青山1 小时前
文本行过滤/筛选 在线工具核心JS实现
前端·javascript·vue.js
时光不负努力1 小时前
编程常用模式集合
前端·javascript·typescript
恋猫de小郭1 小时前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
小岛前端1 小时前
Node.js 宣布重大调整,运行十年的规则要改了!
前端·node.js
OpenTiny社区1 小时前
OpenTiny NEXT-SDK 重磅发布:四步把你的前端应用变成智能应用
前端·javascript·ai编程
梦想CAD控件2 小时前
在线CAD开发包结构与功能说明
前端·javascript·vue.js
张拭心2 小时前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能