当前位置: 首页 > news >正文

Mobx初探

  • 苏格团队
  • 作者:Demian

一、前言

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

二、Mobx 简介

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

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

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

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

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

详细代码如下:

// 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 为:

1.Computed Values

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

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

可见,computed 属性可以响应 observable 属性的变化。

值得一提的是,在 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。

三、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 包装异步函数,这样才可以完成响应式的更新数据。

四、Mobx vs Redux

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

修改数据

中间件

五、总结

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

转载于:https://juejin.im/post/5cbfb60e6fb9a0324936b54b

相关文章:

  • 【云吞铺子】性能抖动剖析(二)
  • react-nativeAndroid打包报错:Daemon: AAPT2 aapt2-3.2.1-4818971-osx Daemon #0
  • 查看文件权限
  • RocketMQ快速上手
  • 4-4 重构get请求+格式化响应数据
  • Redis安装部署踩坑
  • “僕は存在していなかった”-22/7-CG音乐视频制作
  • 数位dp-Bomb
  • TNW-微信公众号各种消息交互
  • 221 springCloud 学习
  • 2018-2019-2 网络对抗技术 20165324 Exp6:信息收集与漏洞扫描
  • 学号20175313 《数据库MySQL(课下作业,必做)》第十周
  • Oomox:定制和创建你自己的 GTK2、GTK3 主题
  • 图论
  • mysql笔记
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • codis proxy处理流程
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • JavaScript异步流程控制的前世今生
  • linux学习笔记
  • PHP 7 修改了什么呢 -- 2
  • React+TypeScript入门
  • React中的“虫洞”——Context
  • Windows Containers 大冒险: 容器网络
  • 彻底搞懂浏览器Event-loop
  • 动态魔术使用DBMS_SQL
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 如何胜任知名企业的商业数据分析师?
  • 一个完整Java Web项目背后的密码
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 如何正确理解,内页权重高于首页?
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​低代码平台的核心价值与优势
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #pragam once 和 #ifndef 预编译头
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (02)Hive SQL编译成MapReduce任务的过程
  • (31)对象的克隆
  • (分布式缓存)Redis持久化
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (黑马C++)L06 重载与继承
  • (六)c52学习之旅-独立按键
  • (十五)使用Nexus创建Maven私服
  • (转)Scala的“=”符号简介
  • (转)visual stdio 书签功能介绍
  • *1 计算机基础和操作系统基础及几大协议
  • .NET连接数据库方式
  • .skip() 和 .only() 的使用
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [2017][note]基于空间交叉相位调制的两个连续波在few layer铋Bi中的全光switch——