Mobx初探

  • 苏格团队
  • 做者:Demian

1、前言

本文是笔者在看了 frontendmaster 的状态管理课程以后,对 mobx 进行的初步学习的总结。html

2、Mobx 简介

mobx 是社区内使用的较为常见的一种状态管理库,mobx 官网称其vue

经过透明的函数响应式编程(transparently applying functional reactive programming - TFRP)使得状态管理变得简单和可扩展react

mobx 主要有如下几个核心特性:git

  • Observable State(可观察状态)
  • Computed Values(计算属性)
  • Reactions(反应,完成页面渲染、日志打印)
  • Actions(动做)

如下介绍将结合部分 mobx 代码,代码地址: 示例代码github

详细代码以下:编程

// html
<div id="console" />;

// js
const { computed, observable, autorun } = mobx;

class Person {
  @observable firstName;
  @observable secondName;

  constructor(firstName, secondName) {
    this.firstName = firstName;
    this.secondName = secondName;
  }

  @computed get fullName() {
    return this.firstName + ' ' + this.secondName;
  }
}

const wdz = new Person('Demian', 'Wang');
const greet = observable.box('good morning! ');

const render = () => {
  document.getElementById('console').innerText = greet + wdz.fullName;
};
// 动态更新dom内容
autorun(render);
复制代码

此时网页 ui 为:redux

1.Computed Values

首先介绍一下计算属性。在上述代码中 fullName 就是计算属性。相信用过 vue 的对这个很熟悉。当咱们在命令行手动修改 wdz 的 firstName 时,wdz 的 fullName 会自动更新babel

此时网页 ui 也发生了实时的变化:app

可见,computed 属性能够响应 observable 属性的变化。frontend

值得一提的是,在 react 的 render 函数中,若是存在不少 props 的计算的话,可使用 get 语法的形式将这部分逻辑抽离:

get fullName() {
  return this.props.firstName + this.props.secondName;
}
render() {
  return <div>{this.fullName}</div>
}
复制代码

这里的 fullName 和可计算属性相似,依据传入的 props 属性动态变化。

2.Observable State

经过在类属性前加上@observable,为该属性添加了可观察功能。

import { observable } from 'mobx';
class Person {
  @observable firstName;

  constructor(firstName) {
    this.firstName = firstName;
  }
}
复制代码

使用装饰器语法很简洁的使得 name 拥有了可观察的功能。

那么 Observable 有什么做用呢?

见如下代码:

const greet = observable.box('good morning! ');
复制代码

咱们为 greet 返回一个 observable 包装过的值,首先咱们试着直接改变 greet 的值

可是,此时网页 ui 没有实时变化:

可见,原始类型在包装过以后, 直接改变引用值不能触发页面动态更新,感兴趣的读者能够点击上面的连接打印出 greet 的属性,就能很直观的认识到 observable 的做用。

如下是简化版的 observable:

// 简单的observable
const observable = value => {
  return {
    value,
    get() {
      console.log('get', this.value);
      return this.value;
    },
    set(newValue) {
      console.log('set', newValue);
      // 向全局通知该数据更新
      report(this.value, newValue);
      this.value = newValue;
    }
  };
};

// reactive代码
eventEmitter.on('report', (oldValue, newValue) => {
  console.log(oldValue, '===>', newValue);
});

// 通知给全局
const report = (oldValue, newValue) => {
  eventEmitter.emit('report', oldValue, newValue);
};
复制代码

主要是使用 value 值存储原始类型,使用 get 获取 value 值,使用 set 更新 value 值。值得注意的是,在更新数据之前,set 方法会根据必定的配置,选择是否向全局发送更新事件,相应的一些 computed 的属性会接收到该事件。

3.Reactions

const render = () => {
  document.getElementById('console').innerText = greet + wdz.fullName;
};
// 动态更新dom内容
autorun(render);
复制代码

当 observable 数据变化后,页面会自动更新 ui。

3、mobx 实战-实现一个 todoList

注:因为 create-react-app 建立的项目默认不能使用装饰器语法,因此笔者暴力的 eject 并安装了相应的 babel 配置。

如下是 todoList 的项目结构:

最终实现效果:

项目地址: todolist

当咱们使用 mobx 维护状态时,store 不像 redux 那样是全局惟一的,咱们能够细粒度地维护一个个数据模型。在中小型的项目中,mobx 的 store 轻便简洁,使用起来很顺滑。

项目中用到的 mobx 特性:

1.observable

主要维护 todolist 的基本状态:待办列表 todolist、新建待办的内容 itemContent 和当前筛选类型 filterType

2.computed

根据当前筛选器的类型,返回对应的 todoList。

3.reactions

筛选器状态变化后,响应式地打印出当前筛选器的状态。

4.actions

点击筛选器后的状态切换和异步事件。这里须要使用 runInAction 包装异步函数,这样才能够完成响应式的更新数据。

4、Mobx vs Redux

二者都是优秀的状态管理工具,均可以帮助开发者完成业务开发。因此抛开业务场景谈论工具优劣是无心义的,笔者这里只是简单列出二者的区别。

修改数据

中间件

5、总结

笔者只是介绍了 mobx 的冰山一角,其做为一种响应式的状态管理库,在中小型项目中有着高效率的表现。响应式的写法、细粒度的 store 管理都体现了 mobx 的灵活性。

相关文章
相关标签/搜索