mobx的使用
MobX
简单、可扩展的 JavaScript 状态管理库。一般和 React 结合使用。
安装
使用命令行安装
npm install mobx --save
。React 绑定库:npm install mobx-react --save
。CDN
浏览器支持
- MobX>=5 版本可运行在任何支持 es6 的浏览器中,不支持 IE11 以下和 Node 5 以下。
- MobX 4 可以运行在任何支持 ES5 的浏览器上,而且也在持续的维护中,但是 MobX4 具有一些局限性,长期维护支持版。
入门
MobX 通过透明的函数响应式编程使得状态管理变得简单和可扩展。MboX 的核心思想就是:
任何源自应用状态的东西都应该自动地获得。
其中包括 UI、数据序列化、服务器通讯等等。
在 React 中使用 MobX。React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而 MobX 提供机制来存储和更新应用状态供 React 使用(类似于 Vue 中的 Vuex)。
MobX 提供了优化应用状态于 React 组件同步的机制,这种机制就是使用响应式虚拟依赖状态图表,它只有在真正需要的时候才更新并且永远保持是最新的。
装饰器
装饰器是一个对类进行处理的函数
基本语法
@xxx
返回函数为装饰器传参
@xxx(value)
添加实例属性
mixin
@fn //基本语法
@fn2(20) //传参
@fn3 //添加实例属性
class Myclass {
@readonly message = "hello";
@noenumerable bar = "foo";
@noenumerable test() {
console.log("hello,test");
}
}
function fn(target) {
target.foo = "bar";
}
function fn2(value) {
return function (target) {
target.count = value;
};
}
function fn3(target) {
target.prototype.foo = "baz";
}
//设置只读
function readonly(target, name, descriptor) {
/* console.log(target); //目标类的.prototype
console.log(name); //被修饰的类成员的名称
console.log(descriptor); // 被修饰的类成员的描述对象 */
descriptor.writable = false;
}
//不可被遍历
function noenumerable(target, name, descriptor) {
// descriptor.enumerable = false;
}
const c1 = new Myclass();
// console.log(c1.message);
for (let key in c1) {
console.log(key, c1[key]);
}
c1.test();
/* console.log(Myclass.foo);
console.log(Myclass.count);
console.log(new Myclass().foo); */
核心 API
其中 observable、
computed、
reactions 和 action
是 MobX 最重要的 API
MObX
改变 observables
observable
Observable 值可以是 JS 基本数据类型、引用类型、普通对象、类实例、数组和映射。
@observable count = 0;
@observable foo = 'bar';
observer
observer
函数/装饰器可以用来将 React 组件转变成响应式组件。 它用 mobx.autorun
包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。 observer
是由单独的 mobx-react
包提供的。observer 由 mobx-react 导入。
@observer
class App extends React.Component {}
computed
根据现有的状态或其它计算值衍生出的值,在多从调用 computed 方法时,计算属性的方法只执行一次,因为它会缓存计算方法,除非方法中的属性改变。用于返回数据。
@computed get totalPrice() {
return this.price * this.count;
}
action
只对修改状态的函数使用动作。配置 mobx 强制使用 action,通过 configure 中的 enforceActions 配置为 observed,不容许在 action 之外修改容器状态。自我认为类似于 React 中的 setState。
configure({
enforceActions: "observed",
});
action.bound
为方法绑定 this。一般情况下 action 都与 bound 连用。
@action.bound change() {
console.log(this);
this.count = 10;
this.foo = 'hello';
this.foo = 'world';
}
action-runInAction
在不想调用 action 函数时,可以直接使用 runInAction 来改变属性的值。
runInAction(() => {
this.count = 100;
});
异步 action
在 action 严格模式下无法直接修改容器中属性的状态,可通过
- 定义 action 函数使用
- 直接调用 action 函数
- runInAction
@action.bound asyncChange() {
setTimeout(() => {
// this.count = 100;
// 1. 定义 action 函数
// this.changeCount()
// 2. 直接调用action函数
// action('changeFoo',()=>{
// this.foo ='hello'
// })()
// 3. runInAction
runInAction(() => {
this.count = 100;
});
}, 100);
}
when
当依赖的数据条件被满足时触发,只执行一次,之后不再处理。如果第一次条件被满足就会被立刻执行。
// 当 count > 100 的时候,只执行一次自定义逻辑when( () => { return store.count > 100; }, () => { console.log('when=> ', store.count); });
reaction
reaction 只有当被观测的数据发生改变的时候,才会执行,reaction 可频繁触发。
reaction( () => { // 执行一些业务逻辑操作,返回数据给下一个函数使用。 return store.count; }, (data, reaction) => { console.log('reaction=> ', data); // 手动停止当前 reaction的监听 reaction.dispose(); });
学习排坑
目前直接使用 npm i mobx mobx-react 时,mobx 下载的版本是 6,目前官方文档还没有更新,所以在下载依赖时,建议在 mobx 后加@5.15.5 这种具体版本号。
mobx-react
import { observer, Provider, inject } from "mobx-react";
Provider
Provider 是一个 React 组件,使用 React 的上下文(context)机制,可以用来向下传递 stores,即把 state 传递给其子组件。
const stores = { mainStore, userStore, commonStore };
ReactDOM.render(
<Provider {...stores}>
{" "}
<App />{" "}
</Provider>,
document.getElementById("container")
);
inject
inject 是一个高阶组件,作用是将组件连接到提供的 stores。具体说是与 Provider 结合使用,从 Provider 提供给应用的 state 数据中选取所需数据,以 props 的形式传递给目标组件。
@inject( 'userStore')@observerexport default class User extends Component{}