Mobx

 

一、Mobx工作流程图

在整个数据流中,通过事件驱动(UI 事件、网络请求…)触发 Actions,在 Actions 中修改了 State 中的值,这里的 State 既应用中的 store 树(存储数据),然后根据新的 State 中的数据计算出所需要的计算属性(computed values)值,最后响应(react)到 UI 视图层。

 

二、Mbox的使用

新建一个mobx目录,在其中新建一个appStore.js文件,专门用于管理整个app的state。appStore中定义一个Component,在组件中:

1:定义需要被全局观察的state,用@observable修饰

@observable state = {
    toDoList: [],
  };

2:定义改变state的行为函数,用@action修饰

@action setToDoList = (payload) => {
     this.state.toDoList.push(payload.toDoItem);
 }

3:定义基于state变化,自动触发的行为函数,用@autorun修饰

autorun(() => {
    console.info('toDoList:', this.state.toDoList);
  });

4:在文件末尾,新建一个该组件的实例,并export

5:mobx-react实现mobx与react的链接(直接在根组件中使用)

import { Provider } from 'mobx-react';
import App from 'widget/App/AppView';
import * as stores from 'config/Stores';
<Provider {...stores}>
  <App />
</Provider>

6:使用 @inject 给组件注入其需要的 store(利用 React context 机制)

通过 @observer 将 React 组件转化成响应式组件,它用 mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件

 

三、Observable Object和Observable Arrays

如果使用observable来修饰一个Javascript的简单对象,那么其中的所有属性都将变为可观察的,如果其中某个属性是对象或者数组,那么这个属性也将被observable进行观察,说白了就是递归调用。

Tips: 简单对象是指不由构造函数创建,而是使用Object作为其原型,或是干脆没有原型的对象。

 

考虑到ES5中原生数组对象中存在一定的限制,所以Mobx将会创建一个类数组对象来代替原始数组。在实际使用中,这些类数组的表现和真正的原生数组极其类似,并且它支持原生数组的所有API,包括数组索引、长度获取等。

但是注意一点,sort和reverse方法返回的是一个新的Observable Arrays,对原本的类数组不会产生影响,这一点和原生数组不一样。

 

四、MobX 追踪属性访问,而不是值

let message = observable({
    title: "Foo",
    author: {
        name: "Michel"
    },
    likes: [
        "John", "Sara"
    ]
})

在内存中看起来像下面这样。 绿色框表示可观察属性。 请注意, 本身是不可观察的!

现在 MobX 基本上所做的是记录你在函数中使用的是哪个箭头。之后,只要这些箭头中的其中一个改变了(它们开始引用别的东西了),它就会重新运行。

 

常见陷阱: console.log

 

const message = observable({ title: "hello" })


autorun(() => {
    console.log(message)
})


// 不会触发重新运行
message.title = "Hello world

在上面的示例中,更新 message 的 title 属性不会被打印出来,因为没有在 autorun 内使用。autorun 只依赖于 message,它不是 observable,而是常量。换句话说,对于 MobX 而言,它没有使用 title,因此与 autorun 无关。

import {
  toJS
} from 'mobx';


autorun(() => {
    console.log(message.title) 
})


autorun(() => {
    console.log(mobx.toJS(message)) // toJS 创建了深克隆,从而读取消息
}

可以使用以上两种方式来打印出message 的 title 属性

 

五、编写异步 Actions (动作)

action 包装/装饰器只会对当前运行的函数作出反应,而不会对当前运行函数所调用的函数(不包含在当前函数之内)作出反应! 这意味着如果 action 中存在 setTimeout、promise 的 then 或 async 语句,并且在回调函数中某些状态改变了,那么这些回调函数也应该包装在 action 中。

 

runInAction 工具函数

注意,runInAction 还可以给定第一个参数作为名称。runInAction(f) 实际上是 action(f)() 的语法糖。

 

import {
  action, runInAction
} from 'mobx';
@action getToDoList = async () => {
  const { data } = await Serv.getToDoList();
  const toDoList = get(data, 'list', []);
  runInAction(() => {
    this.state.toDoList = toDoList;
  });
}

 

六、(@)computed

计算值(computed values)是可以根据现有的状态或其它计算值衍生出的值。 概念上来说,它们与excel表格中的公式十分相似。 不要低估计算值,因为它们有助于使实际可修改的状态尽可能的小。 此外计算值还是高度优化过的,所以尽可能的多使用它们。

 

不要把 computed 和 autorun 搞混。它们都是响应式调用的表达式,但是,如果你想响应式的产生一个可以被其它 observer 使用的值,请使用 @computed,如果你不想产生一个新值,而想要达到一个效果,请使用 autorun。 举例来说,效果是像打印日志、发起网络请求等这样命令式的副作用。

import {
  observable, useStrict, computed,
} from 'mobx';


useStrict(true);


class YaoFangMod {
  @observable state = {
    toDoList: [],
  };


  @computed get length() {
    return this.state.toDoList.length + 1;
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值