原文地址:https://mobxjs.github.io/mobx/getting-started.html

写在前面:本人英语水平有限,主要是写给自己看的,若有哪位同学看到了有问题的地方,请为我指出,非常感谢;

mobx是一个比redux更好的状态管理包,代码量更少,思路更清晰,没有像redux那样复杂的reducer,action (ps: redux的作者也推荐mobx,某大大告诉我的,并没有原话链接)

1.mobx 反应流程

2.the core idea

  State 是每一个应用程序的核心部分,而使用一个不合规范的 State 则是让你的应用充满 bug 和失控的不二法门,或者就是局部变量环绕,让你的 state 失去了同步。有很多框架试图解决这个问题,比如使用不可变的 state,但是这样以来又带来了新的问题,比如数据必须规格化,完整性约束失效等等。并且它变得不可能使用强大的概念,如原型。

  MobX 让整个事情又变简单了:它不允许产生失控的 state。它的理念也很简单:所有可以从 state 中派生的事物,都会自动的派生。

  从概念上讲,Mobx会像Excel 表格一样处理您的应用程序。

  • 首先,有一个 state,它可以是一个object,array,primitives等等任何组成你程序的部分。你可以把这个想象成你应用程序的“单元格”。
  • 然后就是 derivations,一般它是指可以从 state 中直接计算的来的结果。比如未完成的任务的数量,这个比较简单,也可以稍复杂一些比如渲染你的任务显示的html。它类似于你的应用程序中的“公式和图表”。
  • Reactions 和 derivations 很像,主要的区别在于 reactions 并不产生数据结果,而是自动完成一些任务,一般是和 I/O 相关的。他们保证了 DOM 和 网络请求会自动适时地出发。
  • 最后是 actions。Actions 指的是所有会改变 state 的事情,MobX 保证所有 actions 都会有对应的 derivations 和 reactions 相伴,保证同步。

2.A simple todo store...

  理论说的够多的了,看一个例子也许会更明白一些。我们从一个简单的 todo 程序开始。

  为了原创性,让我们从一个非常简单的ToDoStore开始。下面是一个非常直接的TodoStore,它维护着一个todos的集合。没有MobX参与。

class TodoStore {
todos = []; get completedTodosCount() {
return this.todos.filter(
todo => todo.completed === true
).length;
} report() {
if (this.todos.length === )
return "<none>";
return `Next todo: "${this.todos[0].task}". ` +
`Progress: ${this.completedTodosCount}/${this.todos.length}`;
} addTodo(task) {
this.todos.push({
task: task,
completed: false,
assignee: null
});
}
} const todoStore = new TodoStore();

  我们刚刚创建了一个带有todos集合的todoStore实例。用一些对象填充todoStore。为了确保我们看到我们的更改的影响,我们在每次更改后调用todoStore.report并记录它。

  请注意,报表有意总是只打印第一个任务。它使这个例子有点人工,但正如你将看到下面它很好地演示了MobX的依赖关系跟踪是动态的。

 ===》 

3.Becoming reactive

  到目前为止,这段代码没有什么特别之处。但是如果我们可以不再手动调用 report 方法,只声明我们希望在每次状态更改时调用它?我们只需要在想要的地方修改这个 state,所有的汇报都自动来做。

   幸运的是,这正是MobX可以为你做的。自动执行完全取决于状态的代码。这样我们的报表功能就会自动更新,就像电子表格中的图表一样。为了实现这一点,TodoStore必须成为可观察的(observable),以便MobX可以跟踪所有正在进行的更改。让我们改变类就足以实现它。

  同时,completedTodosCount 属性应该被自动派生。通过使用@observable和@computed装饰器,我们可以在对象上引入observable属性:

class ObservableTodoStore {
@observable todos = [];
@observable pendingRequests = ; constructor() {
mobx.autorun(() => console.log(this.report));
} @computed get completedTodosCount() {
return this.todos.filter(
todo => todo.completed === true
).length;
} @computed get report() {
if (this.todos.length === )
return "<none>";
return `Next todo: "${this.todos[0].task}". ` +
`Progress: ${this.completedTodosCount}/${this.todos.length}`;
} addTodo(task) {
this.todos.push({
task: task,
completed: false,
assignee: null
});
}
} const observableTodoStore = new ObservableTodoStore();

  至此!我们将一些属性标记为@observable,以指示MobX这些值可以随时间改变。计算用@computed来装饰,以识别这些可以从状态导出。

  pendingRequests和assignee属性到目前为止未使用,但将在本教程后面使用。为了简洁,本页上的所有示例都使用ES6,JSX和装饰器。但不要担心,所有的装饰在MobX有一个ES5写法。

  在构造函数中,我们创建了一个report()将其包装在mobx.autorun()。mobx.autorun()创建一个运行一次的reaction,然后每当在函数内部使用的任何可观察数据发生变化时,自动重新运行。因为report()用observable todos属性,所以它会在适当时打印报表。这在下一个列表中演示。只需按下运行按钮:

==>

  纯函数,对吧?report自动打印了,同步并且没有泄漏的中间值。如果你仔细查看运行结果的话,你会发现我们的第四句语句没有产生输出,因为我们修改了todos[1]的数据,而我们在report中指明的数据,并没有todos[1]的变化而发生变化。而第五句话修改了todos[0]的数据则输出了。这个例子很好的说明了,autorun不是简单的监视了todos,而是精确到了具体的一项。

 4.Making React reactive

  Ok, so far we made a silly report reactive. Time to build a reactive user interface around this very same store. React components are (despite their name) not reactive out of the box. The @observer decorator from the mobx-react package fixes that by wrapping the React component render method in autorun, automatically keeping your components in sync with the state. That is conceptually not different from what we did with the report before.

  好了,到目前为止我们做了一个愚蠢的 report reactive。是时候用非常相似的store创建一个reactive了。React components(尽管他们的名字)没有反应开箱。

  mobx-react包中的@observer装饰器通过在mobx.autorun()包装React组件的render()方法来实现,自动保持组件与状态同步。这在概念上与我们以前的报告没有什么不同

  下面的清单定义了几个React组件。在那里唯一属于MobX的东西是@observer装饰器。这足以确保每个组件在相关数据更改时单独重新render。您不需要再调用setState,也不必了解如何使用需要配置的选择器或更高级的组件来(subscribe :redux中有 )订阅应用程序状态的适当部分。基本上,所有组件都变得聪明。然而,它们是以愚蠢的,声明性的方式定义的。

@observer
class TodoList extends React.Component {
render() {
const store = this.props.store;
return (
<div>
{ store.report }
<ul>
{ store.todos.map(
(todo, idx) => <TodoView todo={ todo } key={ idx } />
) }
</ul>
{ store.pendingRequests > ? <marquee>Loading...</marquee> : null }
<button onClick={ this.onNewTodo }>New Todo</button>
<small> (double-click a todo to edit)</small>
<RenderCounter />
</div>
);
} onNewTodo = () => {
this.props.store.addTodo(prompt('Enter a new todo:','coffee plz'));
}
} @observer
class TodoView extends React.Component {
render() {
const todo = this.props.todo;
return (
<li onDoubleClick={ this.onRename }>
<input
type='checkbox'
checked={ todo.completed }
onChange={ this.onToggleCompleted }
/>
{ todo.task }
{ todo.assignee
? <small>{ todo.assignee.name }</small>
: null
}
<RenderCounter />
</li>
);
} onToggleCompleted = () => {
const todo = this.props.todo;
todo.completed = !todo.completed;
} onRename = () => {
const todo = this.props.todo;
todo.task = prompt('Task name', todo.task) || todo.task;
}
} ReactDOM.render(
<TodoList store={ observableTodoStore } />,
document.getElementById('reactjs-app')
);

  下一个清单很好地显示,我们只需要改变我们的数据,而不做任何其他事情。 MobX将自动从存储中的状态重新导出和更新用户界面的相关部分。

  运行结果:

5.Working with references

  到目前为止,我们已经创建了observable对象(原型对象和plain对象),数组和基元(primitives)。你可能想知道,在MobX中如何处理引用?我的state是否允许形成图表?在上一个列表中,您可能已经注意到todos有一个assignee 属性。让我们给他们一些值,通过引入另一个“store”(它只是一个glorified数组)包含人,和分配给他们的任务。

   

  那么问题来了,observableTodoStore.todos本来就是@observable的,奈何有要再增加一个呢?

   答:大概因为改变的时候方便?

  We now have two independent stores. One with people and one with todos. To assign an assignee to a person from the people store, we just assigned a reference. These changes will be picked up automatically by the TodoView. With MobX there is no need to normalize data first and to write selectors to make sure our components will be updated. In fact, it doesn't even matter where the data is stored. As long as objects are made observable, MobX will be able to track them. Real JavaScript references will just work. MobX will track them automatically if they are relevant for a derivation. To test that, just try changing your name in the next input box (make sure you have pressed the above Run code button first!).

  我们现在有两个独立的商店。一个人和一个todos。要从people store中分配一个person的代理,我们只需要分配了一个参考。这些更改将由TodoView自动选取。使用MobX,没有必要首先规范化数据,并且编写选择器以确保我们的组件将被更新。事实上,数据存储的位置甚至都不重要。只要对象是可观察的,MobX将能够跟踪它们。真正的JavaScript引用将正常工作。 MobX将自动跟踪它们,如果它们与派生相关。要测试,只需尝试在下一个输入框中更改您的名称(确保您已经按上面的Run代码按钮!)。

  

6.Asynchronous actions

   因为我们的小Todo应用程序中的一切都是从状态派生而来的,所以当状态改变时它并不重要。这使得创建异步操作真的很简单。只需按下面的按钮(多次)来模拟异步加载新的todo项:

  后面的代码真的很简单。我们从更新存储属性pendingRequests开始,让UI反映当前的加载状态。一旦加载完成,我们更新商店的todos并再次减少pendingRequests计数器。只需将此代码段与早期的TodoList定义进行比较,即可了解如何使用pendingRequests属性

7.Conclusion

  就这样!没有样板。只是一些UI组件中的简单的声明性组件,形成我们的完整的UI。这些是完全地,反应性地从我们的state中得到。现在,您可以开始在自己的应用程序中使用mobx和mobx-react包。您到目前为止学到的东西的简短摘要:

  • 使用@observable装饰器或observable(obj or array)函数令对象可以被MobX追踪。
  • @computed装饰器可以用于创建可以从状态自动导出其值的函数。
  • 使用autorun运行依赖于某个可观察状态的函数。这对log,网络请求等很有用.
  • 使用来自mobx-react包的@observer装饰器,使您的React组件真正被动。他们将自动和有效地更新。即使用于具有大量数据的大型复杂应用程序。

  (我这里是不行的)

  可以随意使用上面的可编辑代码块玩一段时间,以获得MobX对所有更改的反应的基本感觉。例如,您可以向报告函数添加一条日志语句,以查看它被调用的时间。或者根本不显示报告,看看它如何影响TodoList的呈现。或仅在特定情况下显示...

8.MobX is not a state container

  人们经常使用MobX作为Redux的替代品。但请注意,MobX只是一个库来解决技术问题,而不是一个架构或甚至状态容器本身。在这个意义上,上面的例子是设计的,并且建议使用适当的工程实践,如在方法中封装逻辑,在商店或控制器等组织它们。或者,正如HackerNews上的某人所说:

  “MobX,它在其他地方被提到,但我不能不赞扬它。在MobX中编写意味着使用控制器/调度程序/操作/管理程序或另一种形式的管理数据流返回到一个架构问题,您可以模式化您的应用程序的需要,而不是默认情况下需要的任何东西比一个Todo应用程序。

十分钟介绍mobx与react的更多相关文章

  1. (十分钟视频教程)nodejs基础实战教程3:react服务端渲染入门篇

    视频截图如下: (具体视频见文末) 前言: 这是小猫的第三篇node教程,本篇内容是由公众号粉丝票选得出的,相信大家对这篇教程是抱有较大希望的,这篇教程由小猫和一位多年的好朋友合作完成(笔名:谷雨,博 ...

  2. 【NLP】十分钟快览自然语言处理学习总结

    十分钟学习自然语言处理概述 作者:白宁超 2016年9月23日00:24:12 摘要:近来自然语言处理行业发展朝气蓬勃,市场应用广泛.笔者学习以来写了不少文章,文章深度层次不一,今天因为某种需要,将文 ...

  3. 十分钟轻松让你认识ASP.NET 5(MVC6)

    ASP.NET 5差不多快发布了.自己也学习了有两个月了.今天给没有接触asp.net 5的同学写一个简单地十分钟教程,教你认识一下asp.net 5. 1.安装kvm 首先,你需要以管理员权限打开c ...

  4. 十分钟了解分布式计算:Google Dataflow

    介绍 Google Cloud Dataflow是一种构建.管理和优化复杂数据处理流水线的方法,集成了许多内部技术,如用于数据高效并行化处理的Flume和具有良好容错机制流处理的MillWheel.D ...

  5. 号外号外:9月13号《Speed-BI云平台案例实操--十分钟做报表》开讲了

    引言:如何快速分析纷繁复杂的数据?如何快速做出老板满意的报表?如何快速将Speed-BI云平台运用到实际场景中?         本课程将通过各行各业案例背景,将Speed-BI云平台运用到实际场景中 ...

  6. 【项目管理和构建】十分钟教程,eclipse配置maven + 创建maven项目(三)

    [项目管理和构建]十分钟教程,eclipse配置maven + 创建maven项目(三) 上篇博文中我们介绍了maven下载.安装和配置(二),这篇博文我们配置一下eclipse,将它和maven结合 ...

  7. [转载]GDB十分钟教程

    转自:http://blog.csdn.net/liigo/article/details/582231/ GDB十分钟教程 作者: liigo原文链接: http://blog.csdn.net/l ...

  8. 十分钟了解MVVMLight

    十分钟了解MVVMLight   前言: 最近看了看开源框架MVVMLight,一直想写一点笔记,但是文笔欠佳,索性就放弃了.那就来翻译一点文章吧. 由于英文水平和技术水平有限,凡是不妥之处,请大家指 ...

  9. PHP学习过程_Symfony_(3)_整理_十分钟学会Symfony

    这篇文章主要介绍了Symfony学习十分钟入门教程,详细介绍了Symfony的安装配置,项目初始化,建立Bundle,设计实体,添加约束,增删改查等基本操作技巧,需要的朋友可以参考下 (此文章已被多人 ...

随机推荐

  1. 谈谈DOMContentLoaded:Javascript中的domReady引入机制

    一.扯淡部分 回想当年,在摆脱写页面时js全靠从各种DEMO中copy出来然后东拼西凑的幽暗岁月之后,毅然决然地打算放弃这种处处“拿来主义”的不正之风,然后开启通往高大上的“前端攻城狮”的飞升之旅.想 ...

  2. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  3. 【开源】.Net Aop(静态织入)框架 BSF.Aop

    BSF.Aop .Net 免费开源,静态Aop织入(直接修改IL中间语言)框架,类似PostSharp(收费): 实现前后Aop切面和INotifyPropertyChanged注入方式. 开源地址: ...

  4. Hbase的伪分布式安装

    Hbase安装模式介绍 单机模式 1> Hbase不使用HDFS,仅使用本地文件系统 2> ZooKeeper与Hbase运行在同一个JVM中 分布式模式– 伪分布式模式1> 所有进 ...

  5. spring源码分析之<context:property-placeholder/>和<property-override/>

    在一个spring xml配置文件中,NamespaceHandler是DefaultBeanDefinitionDocumentReader用来处理自定义命名空间的基础接口.其层次结构如下: < ...

  6. Oracle数据库该如何着手优化一个SQL

    这是个终极问题,因为优化本身的复杂性实在是难以总结的,很多时候优化的方法并不是用到了什么高深莫测的技术,而只是一个思想意识层面的差异,而这些都很可能连带导致性能表现上的巨大差异. 所以有时候我们应该先 ...

  7. J a v a 的“多重继承”

    接口只是比抽象类“更纯”的一种形式.它的用途并不止那些.由于接口根本没有具体的实施细节——也就是说,没有与存储空间与“接口”关联在一起——所以没有任何办法可以防止多个接口合并到一起.这一点是至关重要的 ...

  8. GitHub管理代码-随笔

    公司一直用的SVN进行项目管理,平时便自己折腾了下Git,这里做下GitHub的最简单的记录... 在git上创建仓库等就免谈了,网上也有好多教程,直接从创建之后记录: 在github的readme文 ...

  9. [AlwaysOn Availability Groups]健康模型 Part 1——概述

    健康模型概述 在成功部署AG之后,跟踪和维护健康状况是很重要的. 1.AG健康模型概述 AG的健康模型是基于策略管理(Policy Based Management PBM)的.如果不熟悉这个特性,可 ...

  10. 递归实现n(经典的8皇后问题)皇后的问题

    问题描述:八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后, 使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上 ...