首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MobX状态管理:简洁而强大的状态机

MobX状态管理:简洁而强大的状态机

原创
作者头像
天涯学馆
发布于 2024-08-16 10:34:00
发布于 2024-08-16 10:34:00
82700
代码可运行
举报
文章被收录于专栏:Web大前端Web大前端
运行总次数:0
代码可运行

MobX 是一个用于构建可响应的数据模型的库,它提供了一种声明式的方式来管理状态,使得数据的变化能够自动更新相关的视图。

创建可观察状态(Observable State)

MobX使用@observable装饰器来创建可观察的对象、数组或基本类型,当它们发生变化时,依赖它们的观察者会自动更新。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   import { observable } from 'mobx';

   class Todo {
     @observable title;
     @observable completed;

     constructor(title) {
       this.title = title;
       this.completed = false;
     }
   }

   const todo1 = new Todo("Learn MobX");

可响应的计算值(Computed Values)

使用@computed装饰器创建基于其他可观察值的计算值,这些计算值会根据依赖关系自动更新。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   class TodoList {
     @observable todos = [];
     @computed get completedCount() {
       return this.todos.filter(todo => todo.completed).length;
     }
   }

   const todoList = new TodoList();
   todoList.todos.push(todo1);

动作(Actions)

使用@action装饰器确保状态的改变发生在受控的环境中,这有助于避免在不恰当的地方修改状态。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   class TodoList {
     // ...
     @action addTodo(title) {
       this.todos.push(new Todo(title));
     }

     @action toggleTodo(index) {
       this.todos[index].completed = !this.todos[index].completed;
     }
   }

观察者(Observers)

在React中,使用mobx-react库的observer高阶组件或useObserver Hook,使组件对状态变化作出反应。

代码语言:jsx
AI代码解释
复制
   import React from 'react';
   import { observer } from 'mobx-react-lite';

   const TodoListComponent = observer(({ todoList }) => (
     <ul>
       {todoList.todos.map((todo, index) => (
         <li key={index}>
           {todo.title} - {todo.completed ? 'Completed' : 'Not completed'}
         </li>
       ))}
     </ul>
   ));

   const App = () => {
     const todoList = new TodoList();
     return <TodoListComponent todoList={todoList} />;
   };

反应式编程(Reactive Programming)

MobX的核心在于其反应式系统,当数据变化时,所有依赖它的计算值和观察者都会自动更新,无需手动调用setState。反应式编程是一种编程范式,它强调数据流和变化的传播,使得程序能够自动响应数据变化。

可观察对象(Observables)

MobX使用@observable装饰器或observable函数来创建可观察的值。当这些值发生变化时,依赖它们的任何计算或视图都会自动更新。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   import { observable } from 'mobx';

   class Counter {
     @observable count = 0;
   }

   const counter = new Counter();

   // 观察者自动更新
   autorun(() => {
     console.log(`当前计数是: ${counter.count}`);
   });

   // 修改计数
   counter.count++;
计算值(Computed Values)

@computed装饰器用于创建基于可观察值的计算值。计算值在依赖的可观察值变化时会自动更新。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   class Counter {
     // ...
     @computed get isEven() {
       return this.count % 2 === 0;
     }
   }

   // 计算值自动更新
   autorun(() => {
     console.log(`当前计数是否为偶数: ${counter.isEven}`);
   });

   // 修改计数
   counter.count++;
反应(Reactions)

使用autorunreactionwhen函数创建反应,这些函数会在数据变化时自动执行。autorun每当依赖的可观察值变化时运行,而reaction则在特定条件变化时运行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   // 反应式更新UI
   reaction(
     () => counter.count,
     (newCount) => {
       updateUI(newCount);
     },
   );

   // 基于条件的反应
   when(
     () => counter.count > 10,
     () => {
       console.log('计数超过10了!');
     },
   );
动作(Actions)

@action装饰器或action函数用于标记状态更改的函数。这确保了状态在受控环境中改变,防止了意外的副作用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   class Counter {
     // ...
     @action increment() {
       this.count++;
     }
   }

   counter.increment();

自动追踪依赖(Automatic Dependency Tracking) MobX使用代理(proxies)和访问者模式来自动追踪计算值和反应的依赖。这意味着你不需要手动处理依赖关系,系统会自动处理。

跟踪依赖(Dependency Tracking)

MobX使用代理(proxies)和访问者模式来跟踪哪些计算值和观察者依赖于哪些可观察状态,从而实现高效的更新。

代理(Proxies)

MobX使用ES6的Proxy对象来创建可观察对象的代理。Proxy可以拦截对象的访问和修改操作,这使得MobX能够监听到何时读取或修改可观察状态。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   const observableValue = observable(42);
   const proxyValue = new Proxy(observableValue, mobxHandler); // mobxHandler包含了拦截逻辑
访问者模式(Visitor Pattern)

当访问可观察对象的属性时,MobX会记录访问路径,这称为访问者模式。它创建了一个依赖树,表示哪些计算值或反应函数依赖于哪些可观察状态。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   class ObservableObject {
     @observable prop;
     // ...
   }

   const obj = new ObservableObject();
   autorun(() => {
     console.log(obj.prop);
   });

   // 访问 obj.prop 时,MobX记录了这个依赖
   obj.prop = "new value";
变化通知(Change Notifications)

当可观察状态改变时,MobX会通知所有依赖于这个状态的计算值和反应函数。由于依赖已经被记录,所以只有真正受到影响的计算和反应才会被触发。

最小化更新(Minimized Updates)

依赖追踪确保了只有真正需要更新的计算值和反应函数才会执行。这提高了性能,因为只有在必要时才会重新计算。

优化(Optimizations)

MobX还提供了优化机制,例如,通过使用asFlat、asReference或asStructure等方法,可以控制代理对象如何处理变化,以进一步提高性能。

中间件集成

尽管MobX并不像Redux那样与中间件紧密集成,但你可以使用mobx-react-devtools来监控状态变化,提供类似的时间旅行调试功能。

安装插件

使用npm或yarn安装mobx-react-devtools

代码语言:bash
AI代码解释
复制
   npm install --save mobx-react-devtools
   # 或
   yarn add mobx-react-devtools
在你的应用中引入

在你的主应用程序文件(通常是index.js或App.js)中,导入并插入mobxReactDevTools组件:

代码语言:jsx
AI代码解释
复制
   import { Provider } from 'mobx-react';
   import { mobxReactDevTools } from 'mobx-react-devtools';

   // 假设你已经有了你的store
   const store = new YourStore();

   ReactDOM.render(
     <Provider {...store}>
       <YourApp />
       {/* 在你的应用下方添加DevTools */}
       <mobxReactDevTools />
     </Provider>,
     document.getElementById('root')
   );
启用开发者工具

一旦你的应用运行起来,你可以在浏览器的开发者工具中看到一个新的面板,显示你的MobX状态和变更历史。在Chrome或Firefox中,通常可以通过打开开发者工具,然后选择“.mobx-react-devtools”或“Extensions”面板来找到它。

时间旅行调试(Time Travel Debugging)

虽然mobx-react-devtools不直接提供时间旅行调试,但你可以使用mobx-state-tree库,它与MobX兼容,并提供了时间旅行功能。mobx-state-tree创建了一个可逆的操作历史,允许你回放和重播状态的变更。

TypeScript支持

MobX与TypeScript有很好的集成,可以提供类型安全和更好的代码提示。

类型注解(Type Annotations)

在TypeScript中,你可以为可观察对象、计算值和动作添加类型注解,确保类型安全。

代码语言:typescript
AI代码解释
复制
   import { observable, computed, action } from 'mobx';

   class Counter {
     @observable count: number = 0;

     @computed
     get isEven(): boolean {
       return this.count % 2 === 0;
     }

     @action
     increment(): void {
       this.count++;
     }
   }
接口(Interfaces)

通过定义接口,你可以为可观察对象创建更复杂的类型结构,确保数据模型的一致性。

代码语言:typescript
AI代码解释
复制
   interface Todo {
     id: number;
     title: string;
     completed: boolean;
   }

   class TodoStore {
     @observable todos: Todo[] = [];

     // ...
   }
类型推断(Type Inference)

TypeScript会自动推断计算值的类型,基于它们的依赖。

类型保护(Type Guards)

你可以使用类型保护函数来确保在类型安全的上下文中访问可观察对象。

代码语言:typescript
AI代码解释
复制
   function isTodo(item: any): item is Todo {
     return item && typeof item.id === 'number' && typeof item.title === 'string';
   }

   const todo = getTodoFromSomewhere();

   if (isTodo(todo)) {
     // 在这里,TypeScript知道`todo`是`Todo`类型
     console.log(todo.title);
   }
类型扩展(Type Extensions)

你可以扩展ObservableObject, ObservableArray, 和 ObservableMap的类型,以便更好地描述你的数据。

makeObservable和makeAutoObservable

在MobX 6中,推荐使用makeObservablemakeAutoObservable来初始化可观察状态,它们提供了更好的类型安全和自动类型推断。

代码语言:typescript
AI代码解释
复制
   class TodoStore {
     private todos: Todo[] = [];

     constructor() {
       makeAutoObservable(this);
     }

     // ...
   }

反应式数据流(Reactive Data Flow)

MobX的反应式数据流意味着数据变化会自动传播到依赖的计算和视图,这使得数据模型和UI之间的关系更加清晰。

代码语言:jsx
AI代码解释
复制
import React from 'react';
import { render } from 'react-dom';
import { observable, computed, reaction } from 'mobx';
import { Provider, observer } from 'mobx-react';

// 创建可观察对象
const counterStore = {
  @observable count: 0,

  @action increment() {
    this.count++;
  },

  @computed get doubleCount() {
    return this.count * 2;
  },
};

// 创建一个反应,当count变化时,打印doubleCount
reaction(
  () => counterStore.count,
  (newCount) => {
    console.log(`Double count: ${counterStore.doubleCount}`);
  },
);

// 创建一个React组件,观察count的变化
const Counter = observer(({ store }: { store: typeof counterStore }) => (
  <div>
    <p>Count: {store.count}</p>
    <button onClick={store.increment}>Increment</button>
    <p>Double Count: {store.doubleCount}</p>
  </div>
));

// 渲染应用
render(
  <Provider counterStore={counterStore}>
    <Counter />
  </Provider>,
  document.getElementById('root'),
);

在这个例子中,counterStore是一个包含可观察状态的对象,count属性是可观察的。doubleCount是一个计算值,它基于count自动计算。当count增加时,doubleCountCounter组件都会自动更新,无需手动调用setState。

reaction函数创建了一个观察者,当count改变时,它会打印出doubleCount的新值。这样,数据模型的改变就会自动传播到UI和任何依赖它的计算,形成了一个清晰的反应式数据流。

反应式函数(Reactive Functions)

使用autorun、reaction或when函数,你可以创建基于数据变化的自动执行函数。这些函数会在相关数据改变时自动运行,直到满足特定条件或被手动停止。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    const disposer = reaction(
      () => todoList.completedCount,
      (completedCount) => console.log(`There are ${completedCount} completed todos`),
    );

    // Later, to stop the reaction:
    disposer();

响应式API调用

如果你需要在API调用中使用MobX,可以使用runInAction包裹异步操作,确保状态更新在正确的作用域内。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    async function fetchData() {
      await someAsyncCall().then(data => {
        runInAction(() => {
          // 更新状态
          myStore.setData(data);
        });
      });
    }

微核架构(Microkernel Architecture)

MobX的核心很小,可以根据需要选择性地引入额外的功能,如mobx-state-treemobx-react-form,以增强特定场景下的状态管理和表单处理。

mobx-state-tree

mobx-state-tree是基于MobX的状态管理库,它提供了强大的类型安全、状态快照、时间旅行调试和丰富的异常处理。

代码语言:typescript
AI代码解释
复制
   import { types, onSnapshot, IStateTreeNode } from 'mobx-state-tree';

   const Todo = types.model({
     title: types.string,
     completed: types.boolean,
   });

   const TodoStore = types.model({
     todos: types.array(Todo),
   }).actions(self => ({
     addTodo(title: string) {
       self.todos.push(Todo.create({ title, completed: false }));
     },
   }));

   const store = TodoStore.create({ todos: [] });

   onSnapshot(store, (snapshot) => {
     console.log('State snapshot:', snapshot);
   });

   store.addTodo('Learn MobX');
mobx-react-form

mobx-react-form是一个用于创建和管理表单的库,它与MobX集成良好,提供了验证、提交和重置等功能。

代码语言:jsx
AI代码解释
复制
   import React from 'react';
   import { Form, Field } from 'mobx-react-form';
   import { observable, action } from 'mobx';
   import { Provider, observer } from 'mobx-react';

   const schema = {
     name: 'form',
     fields: ['name', 'email'],
     labels: { name: 'Name', email: 'Email' },
     validators: {
       name: 'required',
       email: 'required|email',
     },
   };

   class MyForm extends Form {
     constructor(values = {}) {
       super(schema, values);
       this.plugins({
         dvr: {},
       });
     }
   }

   const form = new MyForm();

   @observer
   class MyComponent extends React.Component {
     @observable submitting = false;

     @action submitForm = () => {
       this.submitting = true;
       if (form.validate()) {
         alert('Form submitted successfully!');
         form.reset();
       } else {
         form.focus();
       }
       this.submitting = false;
     };

     render() {
       return (
         <Provider form={form}>
           <form onSubmit={this.submitForm}>
             <Field type="text" name="name" />
             <Field type="email" name="email" />
             <button type="submit" disabled={this.submitting}>
               Submit
             </button>
           </form>
         </Provider>
       );
     }
   }

   render(<MyComponent />, document.getElementById('root'));

这两个库扩展了MobX的核心功能,分别针对状态管理和表单处理提供了更高级的抽象。通过这种微核架构,你可以根据项目的具体需求选择合适的工具,保持项目的轻量级和模块化。

与其他库的集成

MobX不仅适用于React,也可以与Vue.js、Angular和其他库集成。此外,它还可以与Redux或其他状态管理库共存,用于特定的场景。

热重载和开发工具

MobX与mobx-react-devtools插件配合使用,提供了在开发过程中查看数据流、跟踪依赖和性能分析的能力,支持热重载,方便快速迭代。

性能优化

MobX的响应式系统会自动跟踪依赖,仅在必要时更新视图,这通常比手动触发更新更高效。然而,如果遇到性能问题,可以使用makeObservable或makeAutoObservable的asStructure或asReference选项,以及trackTransitions来调整性能。

设计模式

MobX鼓励使用如MVC(Model-View-Controller)、MVVM(Model-View-ViewModel)或MST(MobX State Tree)等设计模式,以更好地组织和管理状态。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MobX
也就是说,只要知道哪些东西是状态相关的(源于应用状态),在状态发生变化时,就应该自动完成状态相关的所有事情,自动更新UI,自动缓存数据,自动通知server
ayqy贾杰
2019/06/12
1.3K0
MobX
各流派 React 状态管理对比和原理实现
在 React 诞生之初,Facebook 宣传这是一个用于前端开发的界面库。在大型应用中,如何处理好 React 组件通信和状态管理就显得非常重要。
尹光耀
2022/03/22
3.3K0
各流派 React 状态管理对比和原理实现
Mobx实践
由于redux需要写很多繁琐的action和reducer,很多项目也没有复杂到需要用到redux的程度却强上了redux,导致不少人对redux深恶痛绝。mobx是另一种流行的状态管理方案,这里分享一下我最近使用mobx的经验。
尹光耀
2021/10/19
1K0
MobX 和 React 十分钟快速入门
这个教程将在十分钟内向你详解 MobX 的所有重要概念。MobX 是一个独立的库,但是大部分人将它和 React 共同使用,所以本教程将重点讲解他们的结合使用。
疯狂的技术宅
2019/03/27
1.8K0
MobX 和 React 十分钟快速入门
博文精选|MobX — 10分钟极速入门 MobX 与 React
http://eyehere.net/2016/mobx-getting-started/(点击阅读原文前往)
java达人
2018/12/18
6140
状态管理库 MobX 和 react
很多人把 MobX 当作另外一个 Redux,但是它仅仅是一个库,不是一个什么架构。上面的例子还是需要程序员自己去组织逻辑和 store 或者控制器什么的.
西南_张家辉
2021/02/02
6830
MobX学习之旅
但是,如果仅仅想要在被观察的变量有变化的时候触发,而不是立即执行autorun,那么我们可以用到reaction了;
全栈程序员站长
2022/06/29
1.7K0
用MobX管理状态(ES5实例描述)-4.常用工具方法
MobX是一个简单有效的状态管理库,以派生(derive)的概念为核心,以观察者模式为手段,达到了修改数据自动更新界面等目的 正因为其本身提供了包装react的方法,可以简洁的改善react组件,所以官网文档和几乎所有教程都以react和ES7的装饰修饰符等特性为切入点 但MobX在传统的ES5环境中也能良好工作,本文尝试以此为出发点,探讨在既有的非react项目中直接引入MobX并用其整理重构老代码的方法 没有babel、webpack、JSX...那么多的套路!直接上手先,走你~ [IV]. 常用工具方
江米小枣
2020/06/15
1.1K0
【MobX】MobX 简单入门教程
<img src="http://images.pingan8787.com/blog/mobx.png" width="120px"/>
pingan8787
2019/10/24
1.7K0
【MobX】390- MobX 入门教程(上)
observable 是一种让数据的变化可以被观察的方法,底层是通过把该属性转化成 getter / setter 来实现的。。
pingan8787
2019/10/30
9950
【MobX】390- MobX 入门教程(上)
实现简版 react 状态管理器 mobx
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
测不准
2022/08/07
1.6K0
实现简版 react 状态管理器 mobx
用MobX管理状态(ES5实例描述)-2.可观察的类型
用observable.shallowObject(value)方法可以实现“浅观察”,只自动响应“浅层”的子属性
江米小枣
2020/06/15
8400
用MobX管理状态(ES5实例描述)-1.核心概念和基本流程
MobX是一个简单有效的状态管理库,以派生(derive)的概念为核心,以观察者模式为手段,达到了修改数据自动更新界面等目的 正因为其本身提供了包装react的方法,可以简洁的改善react组件,所以官网文档和几乎所有教程都以react和ES7的装饰修饰符等特性为切入点 但MobX在传统的ES5环境中也能良好工作,本文尝试以此为出发点,探讨在既有的非react项目中直接引入MobX并用其整理重构老代码的方法 没有babel、webpack、JSX...那么多的套路!直接上手先,走你~ [I]. 核心概念和基
江米小枣
2020/06/15
6050
Flutter与MobX的那些事
在以前的一篇文章中,半行代码 介绍到在 Flutter 里面使用 MobX, 今天我们就来聊聊 Flutter 和 MobX 的那些事。
烧麦程
2022/05/10
1K0
Flutter与MobX的那些事
【MobX】391- MobX 入门教程(下)
在上一部分内容中,我们了解到,对可观察的数据做出反应的时候,需要我们手动修改可观察数据的值。这种修改是通过直接向变量赋值来实现的,虽然简单易懂,但是这样会带来一个较为严重的副作用,就是每次的修改都会触发 autorun 或者 reaction 运行一次。多数情况下,这种高频的触发是完全没有必要的。
pingan8787
2019/10/30
1K0
【MobX】391- MobX 入门教程(下)
mobx 入门
mobx 响应式状态管理库 安装 // npm npm i --save mobx // yarn yarn add mobx 基础概念 所谓的响应式,既是将原有数据结构,例如 数组,对象等转变为可观察对象, 通过对可观察对象的监控,当数据变化做出对应的动作,所以可以大概归纳为: 构建观察对象 设置响应动作 在mobx中构建观察对象存在两种模式 函数模式 装饰器模式(针对类定义) 函数模式 创建观察对象 // 引入mobx import { observable } from 'mobx' // 对
copy_left
2019/08/21
1.2K0
用MobX管理状态(ES5实例描述)-3.常用API
除了上面提过的在类实例里使用 getter/setter 和 computed(), computed(expression)也可以直接用来当作一个独立的函数:
江米小枣
2020/06/15
5110
状态管理的概念,都是纸老虎
不管是Vue,还是 React,都需要管理状态(state),比如组件之间都有共享状态的需要。什么是共享状态?比如一个组件需要使用另一个组件的状态,或者一个组件需要改变另一个组件的状态,都是共享状态。
Nealyang
2021/04/20
5.6K0
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
引言 界面: Vue.js 3 JavaScript 超集: TypeScript 包管理器: pnpm 前端工程化/打包: Vite 路由: Vue Router 状态管理: Pinia CSS 预处理器: Less 代码格式化: Prettier 代码质量: ESLint 预览
yiyun
2023/07/17
1.4K0
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
🚀🚀🚀初识mobx,以及mobx-react使用
六月底因为前司经济性裁员,10天内疯狂面试拿到好几个offer(外包字节、外包学而思和一些不知名的小公司),果然是树挪死人挪活,最后选择了还不错的公司,新公司主要是做机器人软件和云端管理软件的,前景还算可以。随后会整理最近的面经(已经在整理中了,是React方向),敬请期待。
萌萌哒草头将军
2024/07/14
3140
🚀🚀🚀初识mobx,以及mobx-react使用
相关推荐
MobX
更多 >
LV.3
这个人很懒,什么都没有留下~
领券
一站式MCP教程库,解锁AI应用新玩法
涵盖代码开发、场景应用、自动测试全流程,助你从零构建专属AI助手
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档