资讯专栏INFORMATION COLUMN

mobx——rudex的简单替代品

DevWiki / 1181人阅读

摘要:是一个的简单可扩展的状态管理库。它的副作用是自动更新。该函数返回一个值,当返回值为的时候,才会继续触发第一个函数。当返回值为时,不再继续监听。包含一个,该值用来区分执行事件的类型。

mobx 能干什么

使用 react 写小型应用,数据、业务逻辑和视图的模块划分不是很细是没有问题的。在这个阶段,引入任何状态管理库,都算是奢侈的。但是随着页面逻辑的复杂度提升,在中大型应用中,数据、业务逻辑和视图,如果不能很好的划分,就很有可能出现维护难、性能低下的问题。

业内比较成熟的解决方案有 redux,但是 redux 使用过程中,给我的感觉是太复杂和繁琐。那么为什么不简单一点呢?mobx 的核心理念是 简单、可扩展的状态管理库。这可能正是你想要的。

react 关注的状态(state)到视图(view)的问题。而 mobx 关注的是状态仓库(store)到的状态(state)的问题。

核心的概念1

mobx 最最核心的概念只有2个。 @observable@observer ,它们分别对应的是被观察者和观察者。这是大家常见的观察者模式,不过这里使用了,ES7 中的 装饰器。

使用 @observable 可以观察类的值。

这里使用 @observable 将 Store 的 todos 变为一个被观察的值。

observable

仓库

// 这里引入的是 mobx
import {observable} from "mobx";

class Store {
  @observable todos = [{
    title: "todo标题",
    done: false,
  }];
}
observer

mobx 组件

然后再使用 @observer ,将组件变为观察者,响应 todos 状态变化。
当状态变化时,组件也会做相应的更新。

// 这里引入的是 mobx-react
import {observer} from "mobx-react";

@observer
class TodoBox extends Component  {
  render() {
    return (
      
    {this.props.store.todos.map(todo =>
  • {todo.title}
  • )}
) } }

完整的 demo 如下。

import React, {Component} from "react";
import { render } from "react-dom";
import {observable} from "mobx";
import {observer} from "mobx-react";

// 最简单的 mobx 就是一个观察者模式

class Store {
  // 被观察者
  @observable todos = [{
    title: "完成 Mobx 翻译",
    done: false,
  }];
}

// 观察者
@observer
class TodoBox extends Component  {
  render() {
    return (
      
    {this.props.store.todos.map(todo =>
  • {todo.title}
  • )}
) } } const store = new Store(); render( , document.getElementById("root") );

通过以上的简单的例子,展现了 mobx 分离数据、视图的能力。

核心概念2

这一小节要介绍的两个概念虽然也是核心概念,但是是可选的。

前面例子,只讲了状态的读取,那么状态应该如何写入呢?

答案是直接写入!

@observer
class TodoBox extends Component  {
  render() {
    return (
      
    {this.props.store.todos.map( (todo,index) =>
  • {todo.title}
  • )}
{ // 直接修改仓库中的状态值 this.props.store.todos[0].title = "修改后的todo标题" }} value="点我"/>
) } }

细心的朋友一定发现了奇怪的地方,react 官方说过 props 值不能直接修改,但是引入 mobx 后 props 可以直接修改了,这太奇怪了!

解决办法就是 mobx 的下一个概念 action

actions

首先在 Store 中,定义一个 action。

class Store {
  @observable todos = [{
    title: "todo标题",
    done: false,
  }];
  @action changeTodoTitle({index,title}){
    this.todos[index].title = title
  }
}

在 Component 中调用,这样通过 action 的方法,就避免了直接修改 props 的问题。

 {
  this.props.store.changeTodoTitle({index:0,title:"修改后的todo标题"});
}} value="点我"/>

可以通过引入 mobx 定义的严格模式,强制使用 action 来修改状态。

import {useStrict} from "mobx";

useStrict(true);
computed values

在有些时候,state 并不一定是我们需要的最终数据。例如,所有的 todo 都放在 store.todos 中,而已经完成的 todos 的值(store.unfinishedTodos),可以由 store.todos 衍生而来。

对此,mobx 提供了 computed 装饰器,用于获取由基础 state 衍生出来的值。如果基础值没有变,获取衍生值时就会走缓存,这样就不会引起虚拟 DOM 的重新渲染。

通过 @computed + getter 函数来定义衍生值(computed values)。

import { computed } from "mobx";

class Store {
  @observable todos = [{
    title: "todo标题",
    done: false,
  },{
    title: "已经完成 todo 的标题",
    done: true,
  }];

  @action changeTodoTitle({index,title}){
    this.todos[index].title = title
  }

  @computed get finishedTodos () {
    return  this.todos.filter((todo) => todo.done)
  }
}

mobx 有一套机制,如果衍生值(computed values)所依赖的基础状态(state)没有发生改变,获取衍生值时,不会重新计算,而是走的缓存。因此 mobx 不会引起过度渲染,从而保障了性能。

当渲染的值为 finishedTodos ,点击修改标题,不会在控制台打印 "render";
换成 todos,就会打印 "render".
这是由于已完成的 todos 值没有改变,所以不会重新计算,而是走的缓存。因此不会调用 render 方法。

完整 demo 如下

import React, {Component} from "react";
import { render } from "react-dom";
import {observable, action, computed,useStrict} from "mobx";
import {observer} from "mobx-react";

useStrict(true);


class Store {
  @observable todos = [{
    title: "todo标题",
    done: false,
  },{
    title: "已经完成 todo 的标题",
    done: true,
  }];

  @action changeTodoTitle({index,title}){
    this.todos[index].title = title
  }

  @computed get unfinishedTodos () {
    return  this.todos.filter((todo) => todo.done)
  }
}


@observer
class TodoBox extends Component  {

  render() {
    console.log("render");
    return (
      
    { /* 把 unfinishedTodos 换成 todos,点击修改标题就会在控制台打印 "render".*/ } {this.props.store.unfinishedTodos.map( (todo,index) =>
  • {todo.title}
  • )}
{ this.props.store.changeTodoTitle({index:0,title:"修改后的todo标题"}); }} value="修改标题"/>
) } } const store = new Store(); render( , document.getElementById("root") );
小结

翻译了官网的一段文章,就拿过来做小结了。

mobx 是一个的简单、可扩展的状态管理库。它背后的哲学非常简单:

应用程序 state 是最基础的数据。任何可以从 state 中衍生出来的数据,都应该自动的被衍生出。

actions 是唯一能够改变 state 的方法。

state 是最基础的数据,它不应该包含冗余的和派生的数据。

computed values 派生值是通过纯函数从 state 中派生而来的。当派生值依赖的状态发生变化了,Mobx 将会自动更新派生值。如果依赖的状态没有改变,mobx 会做优化处理。

reactions 也是派生数据,是从 state 中派生而来的。它的副作用是自动更新 UI。(注:mobx 有一个 reaction 接口,当 state 改变时,就会调用它的回调。UI 是通过 reaction 更新的。)

React 和 MobX 是非常强大的组合。React 提供了将应用状态映射为可渲染的组件树的机制。MobX 提供存储和更新应用状态的机制,供 React 使用。

React 和 MobX 提供了开发过程中常见问题的解决方案。 React 通过使用虚拟 DOM,减少了对浏览器 DOM 的操作。MobX 通过使用了响应式虚拟依赖状态图(reactive virtual dependency state graph) ,提供了应用程序状态与 React 组件同步的机制,这样 state 只会在需要时更新才会更新。(译者注:这段有点难理解,大概的意思是 Mobx 关注的是 store 到 state 的过程,React 关注的是 state 到 view 的过程)。

辅助函数

在实际开发中,需要用到不少 mobx 的辅助函数,这些辅助函数一共 14 个,挑了一些列举如下。

autorun
observable 的值初始化或改变时,自动运行。

trasaction
批量改变时,通过 trasaction 包装,只会触发一次 autorun。

extendsObservable
对类的属性或实例,进行监听。

observable
对普通对象进行监听。

map
使用 asMap 将对象转化为 map。

action-strict
在 mobx.usrStrict(true)时,只能通过 action 触发值的改变。

when
类似 autorun.

mobx.when 第一个参数是一个函数,初始化时也会自动执行。该函数返回一个 boolean 值,当返回值为 true 的时候,才会继续触发第一个函数。当返回值为 flase 时,不再继续监听。这时会执行 mobx.when 的第二个参数,这个参数也是一个函数。

reaction
类似 autorun.

reaction 不会在初始化时执行,只会在值改变的时候执行。

该函数有 2 个值,第一个参数是一个函数,返回监听的值.
第二个参数,也是一个函数,会在值改变的时候执行。

spy
类似 aoturun.

监听所有 mobx 的事件。

包含一个 type ,该值用来区分执行事件的类型。

whyRun
用于调试,打印 autorun 为什么会触发。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86674.html

相关文章

  • 【译】Redux 还是 Mobx,让我来解决你困惑!

    摘要:我现在写的这些是为了解决和这两个状态管理库之间的困惑。这甚至是危险的,因为这部分人将无法体验和这些库所要解决的问题。这肯定是要第一时间解决的问题。函数式编程是不断上升的范式,但对于大部分开发者来说是新奇的。规模持续增长的应 原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用...

    txgcwm 评论0 收藏0
  • Redux三部曲之曲一《还阔以》

    摘要:想学习下全家桶中的,刚好看到了阮一峰老师的入门文章,受益匪浅。官方的解释是是容器,提供可预测化的状态管理。和,寓意为派遣。这是发出的唯一方法。另外方法会返回一个函数,我们如果要解除监听,就可以调用这个函数。 背景 我:您好!我对此职位感兴趣,可以聊聊吗? 招聘者:您好!感谢关注。方便发一份您的简历吗? 几分钟后。。。 招聘者:请过用过react吗? 我:只看过一些项目,...

    ThreeWords 评论0 收藏0
  • Redux三部曲之曲一《还阔以》

    摘要:想学习下全家桶中的,刚好看到了阮一峰老师的入门文章,受益匪浅。官方的解释是是容器,提供可预测化的状态管理。和,寓意为派遣。这是发出的唯一方法。另外方法会返回一个函数,我们如果要解除监听,就可以调用这个函数。 背景 我:您好!我对此职位感兴趣,可以聊聊吗? 招聘者:您好!感谢关注。方便发一份您的简历吗? 几分钟后。。。 招聘者:请过用过react吗? 我:只看过一些项目,...

    YacaToy 评论0 收藏0
  • Redux 问题:React、MobX 和 Realm 能解决吗?

    摘要:它是由一个非常聪明的人开发的,用来缓解在单页面应用中管理状态的问题。的问题没有一种适合所有场景的完美工具。为设计的是世界的另一个新增内容,但目前仅适用于。这将导致最后期限延长,并且留下更多需要我们维护的代码。 原文:The Problems with Redux: Can React, MobX, and Realm save us? 作者:Erich Reich 首先,我不讨厌 ...

    snifes 评论0 收藏0
  • react-redux 开发实践与学习分享

    摘要:简介是一个状态管理的库,由基础上开发出来,与的主要区别是只有一个,关于,后文会详述。这个函数接受四个参数,它们分别是,,和。之前在注册页面,如果没有满足相关条件,则触发的行为。具体定义了项目中触发的行为类别,通过属性来区别于不同的行为。 redux简介 redux是一个js状态管理的库,由flux基础上开发出来,与flux的主要区别是只有一个store,关于store,后文会详述。在各...

    imccl 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<