Mobx简单使用

683 阅读3分钟

mobx简单介绍

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

mobx简单使用

1.创建store

以一个计数器为例,创建文件store/Counter.ts,新建一个Counter类,使用makeObservable方法将类的属性和方法变成响应式,并导出实例
:mobx中的每一个store都应该只初始化一次

// store/Counter.ts
import {action, makeObservable, observable} from 'mobx'
class Counter {
  count = 0
  constructor(){
    makeObservable(this, {
       count: observable,// 参数1:target,把谁变成响应式变量(可观察)- observable
       increment: action,// 参数2:指定哪些属性或者方法变成可观察 - action
       decrement: action,
       reset: action,
     })
  }
  
  increment(){
    this.count++
  }
  decrement(){
    this.count--
  }
  reset(){
    this.count = 0
  }
}
const counter = new Counter()
export default counter 

2.导出store

在组件中使用,需要在其他文件中引入store,即可使用其属性方法,注意需要引入observer,observer是一个高阶组件函数,需要包裹一个组件,这样组件才会更新

// App.tsx
import counter from './store/Counter';

import { observer } from 'mobx-react'

function App() {
  const {cart, counter} = useStore()
  return (
    <div className="App">
      <h3>计数器案例</h3>
      <div>点击次数:{counter.count}</div>
      <button onClick={()c=> ounter.increment()}>加1</button>
      <button onClick={()c=> ounter.decrement()}>减1</button>
      <button onClick={() => counter.reset()}>重置</button>
    </div>
  );
}
export default observer(App);

3.this指向问题

默认class中的方法不会绑定this,this指向取决于如何调用。Counter里面的方法的this没有绑定,因此需要通过箭头函数的形式使用

<button onClick={()=> counter.increment()}>加1</button>

要想直接使用,需要在Counter里面的makeObservable的使用通过action.bound绑定this的指向

    makeObservable(this, {
       count: observable,
       increment: action.bound,
       reset: action.bound,
     })

此时组件中即可直接使用store的方法

<button onClick={counter.increment}>加1</button>

4.计算属性及监听属性

mobx的computed可以用来从其他可观察对象中派生信息,具有以下特点:

  • 采用惰性求值,会缓存其输出,并且只有当其依赖的可观察对象被改变是才会重新计算
  • 其前面必须使用get进行修饰
  • 还需要通过makeObservable方法指定
    以double方法为例
makeObservable(this, {
    count: observable,
    increment: action.bound,
    reset: action.bound,
    double: computed,//指定计算属性
})
get double(){
  return this.count * 2
}

5.使用注解装饰器

@observable定义可观察对象,使用@observable对一个属性进行修饰时,该属性就成为了一个可观察对象,我们可以在它上面绑定reaction或者computed函数来实现对数据的监听和对数据的计算。

import { observable } from 'mobx';

class Counter {
  @observable count = 0;

  increment() {
    this.count++;
  }
}

const counter = new Counter();

console.log(counter.count); // 输出: 0
counter.increment();
console.log(counter.count); // 输出: 1

注:该变量虽然值被改变了,但组件不会重新渲染。

@action将方法标记为一个动作(action),@action 确保这个方法内部对可观察数据的修改是被允许的,同时也能够通知系统进行相应的响应。

import { observable, action } from "mobx";

class Store {
  @observable count = 0;

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

const myStore = new Store();
myStore.increment(); // 自动触发更新,并触发相关组件的更新

@computed将函数或getter方法转换为可观察的计算属性,@computed可以定义一个响应式的计算属性,当其依赖的可观察数据发生变化时,它会自动重新计算并更新自身的值。

import { observable, computed } from "mobx";
class Store {
    @observable items = [];
    
    @computed get itemCount() {
        return this.items.length;
    }
}

const myStore = new Store();
myStore.items.push("item 1");
console.log(myStore.itemCount); // 输出:1

注意
需要在运行环境配置对JavaScript装饰器的支持

  • tsconfig.json
{
  "compilerOptions": {
    "target": "ES5", // 或者你的目标环境
    "experimentalDecorators": true,
    "lib": ["ES2015"],
    "module": "commonjs"
  }
}

这样就不会报错了,但是如果store的constructor里不加下面这句可能会失去响应式特性

constructor() { makeAutoObservable(this); }

6.使用makeAutoObservable

在MobX 6中,推荐使用makeAutoObservable来自动跟踪所有属性和方法,你不需要手动为每个属性和方法添加装饰器,makeAutoObservable会自动识别并应用@observable@action装饰器。

import { makeObservable, makeAutoObservable, observable } from 'mobx';

class StoreWithMakeObservable {
  value = 0;

  constructor() {
    makeObservable(this, {
      value: observable,
    });
  }
}

class StoreWithMakeAutoObservable {
  value = 0;

  constructor() {
    makeAutoObservable(this);
  }
}

const store1 = new StoreWithMakeObservable();
const store2 = new StoreWithMakeAutoObservable();

console.log(store1.value); // 输出:0
store1.value = 10;
console.log(store1.value); // 输出:10

console.log(store2.value); // 输出:0
store2.value = 20;
console.log(store2.value); // 输出:20