十分钟介绍mobx与react

时间:2022-08-27 10:11:36

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

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

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

1.mobx 反应流程

十分钟介绍mobx与react

2.the core idea

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

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

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

十分钟介绍mobx与react

  • 首先,有一个 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的依赖关系跟踪是动态的。

十分钟介绍mobx与react ===》 十分钟介绍mobx与react

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属性,所以它会在适当时打印报表。这在下一个列表中演示。只需按下运行按钮:

十分钟介绍mobx与react==>十分钟介绍mobx与react

  纯函数,对吧?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将自动从存储中的状态重新导出和更新用户界面的相关部分。

十分钟介绍mobx与react

  运行结果:

十分钟介绍mobx与react

5.Working with references

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

 十分钟介绍mobx与react  十分钟介绍mobx与react

  那么问题来了,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代码按钮!)。

  十分钟介绍mobx与react

6.Asynchronous actions

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

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

十分钟介绍mobx与react

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与react

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

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

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

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

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

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

  3. 十分钟轻松让你认识ASP&period;NET 5&lpar;MVC6&rpar;

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

  4. 十分钟了解分布式计算&colon;Google Dataflow

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

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

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

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

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

  7. &lbrack;转载&rsqb;GDB十分钟教程

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

  8. 十分钟了解MVVMLight

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

  9. PHP学习过程&lowbar;Symfony&lowbar;&lpar;3&rpar;&lowbar;整理&lowbar;十分钟学会Symfony

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

随机推荐

  1. 【夯实PHP基础】PHP的反射机制

    本文地址 分享提纲: 1. 介绍 2. 具体例子 2.1 创建Persion类 2.2 反射过程 2.3 反射后使用 1. 介绍 -- PHP5添加了一项新的功能:Reflection.这个功能使得p ...

  2. windows上如何搭建Git Server

    Git在版本控制方面,相比与SVN有更多的灵活性,对于开源的项目,我们可以托管到Github上面,非常方便,但是闭源的项目就会收取昂贵的费用.那么私有项目,如何用Git进行代码版本控制呢?我们可以自己 ...

  3. 面向过程部分 Java 和 C&plus;&plus; 的区别

    前言 Java 和 C++ 在面向过程部分区别并不大,但还是有的,本文罗列了这些区别. 在 Java 中: 1. 数据类型的范围和机器无关 2. 加上前缀 0b 可以表示二进制数,如 0b1001 就 ...

  4. Codeforces Round &num;147 &lpar;Div&period; 2&rpar;

    A. Free Cash 判断值相同的最长长度. B. Young Table 按从上到下,从左到右排序,每个位置最多交换一次. C. Primes on Interval \(p_i\)表示位置\( ...

  5. 举例说明划分子网,路由器IP地址

    划分子网的方法是从网络的主机号借用若干位作为子网号,主机号相应地减少了同样的位数.在划分子网前,IP地址是两级结构的:网络号,主机号. 划分子网后,两级IP地址在本单位内部就变为三级IP地址:网络号, ...

  6. Nginx简介与安装

    | 简介 Nginx是一个高性能的HTTP和反向代理服务器,可以作为负载均衡服务器,也是一个IMAP/POP3/SMTP服务器.它的特点是占有内存少,并发能力强.目前有很多大型公司都在使用Nginx, ...

  7. LeetCode724&period; 寻找数组的中心索引

    1.题目描述 给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法. 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和. 如果数组不存在中 ...

  8. Atitit 支出分类表 会计科目&lpar;1&rpar;资产&lpar;2&rpar;负债&lpar;3&rpar;资本&lpar;4&rpar;收益&lpar;5&rpar;费用&lpar;成本&rpar; 资产分类表 attilax总结

    Atitit 支出分类表  会计科目(1)资产(2)负债(3)资本(4)收益(5)费用(成本)  资产分类表 attilax总结 会计科目对一般不懂会计的管理人员,常会有莫测高深的感觉,因此不仅不愿去 ...

  9. Spark实现K-Means算法

    K-Means算法是一种基于距离的聚类算法,采用迭代的方法,计算出K个聚类中心,把若干个点聚成K类. MLlib实现K-Means算法的原理是,运行多个K-Means算法,每个称为run,返回最好的那 ...

  10. Java Web中Kaptcha实现验证码

    首先进行导入相应的jar包: 1.如果是maven项目,在你的pom文件中进行添加如下代码,将自动下载jar包到你的工程中: <dependency>            <gro ...