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