审核中~
溜忙之道
首页
溜忙手册
offer之道
项目Git
写文章
登录
·
注册
登录
没有账号,去注册
注册
已有账号,去登录
博客
mobx简介
南易_站长
阅读量:13336
关注
mobx简介
[官方文档-传送](https://cn.mobx.js.org/) MobX是响应式编程,实现状态的存储和管理。使用MobX将应用变成响应式可归纳为三部曲: > 1. 定义状态并使其可观察 > 2. 创建视图以响应状态的变化 > 3. 更改状态 在介绍这三个步骤之前,我们先了解下MobX的核心API。 # 一、MobX核心API ## 1. Observable > observable是将类属性等进行标记,实现对其的观察。三部曲中的第一曲,就是通过Observable实现的。 ![null](//upload-images.jianshu.io/upload_images/10255494-17dddb851134a133.png?imageMogr2/auto-orient/strip|imageView2/2/w/964/format/webp) observable 创建observable的方式很多,推荐使用ES7的装饰器(`@observable`),如何开启装饰器,后面将会介绍。 observable的value值的类型参照上图,observable包装后返回对应类型的值,如Observable Object等。 ## 2. Actions > 动作,通过action改变state。三部曲中的第一曲通过action创建一个动作。action函数是对传入的function进行一次包装,使得function中的observable对象的变化能够被观察到,从而触发相应的衍生。 ![null](//upload-images.jianshu.io/upload_images/10255494-d849814926cbc76f.png?imageMogr2/auto-orient/strip|imageView2/2/w/724/format/webp) action * `action(name,fn)`:对fn函数进行包装/装饰,name将被用作调试名。 * `runInAction`:工具函数,是创建异步action的一种方式。 action只会对当前包装/装饰的函数做出反应,而不会对当前运行函数所调用的函数(不包含在当前函数之内)作出反应!这意味着如果 action 中存在 setTimeout、promise 的 then 或 async 语句,并且在回调函数中某些状态改变了,那么这些回调函数也应该包装在 action 中。 runInAction(f)实际上是action(f)()的语法糖。 * `强制action`:设置强制模式后,action必须添加,否则报错。 ## 3. 衍生 > 对observable的响应。三部曲中的第二部的实现方式。 ![null](//upload-images.jianshu.io/upload_images/10255494-0fde9c88d7def904.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp) 衍生 衍生主要分为Reactions和Computed values。其中reactions是自动响应状态变化的副作用,如UI变化、控制台输出、后台服务传送数据。而Computed values(计算值)是自动响应状态变化的值。 * `observer`:包裹react组件的高阶组件,在render方法中,使用observable包装/装饰的属性。 * `autorun`:当你想创建一个响应式函数,但是该函数永远没有观察者,此时使用autorun。这通常是当你需要从反应式代码桥接到命令式代码的情况,例如打印日志、持久化或者更新UI的代码。 当使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发。 经验法则:如果你有一个函数应该自动运行,但不会产生一个新的值,请使用autorun。 其余情况都应该使用 computed。 * `when`: 观察并运行给定的 predicate,直到返回true。 一旦返回 true,给定的 effect 就会被执行,然后 autorunner(自动运行程序) 会被清理。 该函数返回一个清理器以提前取消自动运行程序。 * `reaction`: autorun 的变种,对于如何追踪 observable 赋予了更细粒度的控制。 它接收两个函数参数,第一个(数据 函数)是用来追踪并返回数据作为第二个函数(效果 函数)的输入。 在执行 效果 函数时访问的任何 observable 都不会被追踪。 * `computed`:计算值(computed values)是可以根据现有的状态或其它计算值衍生出的值,创建的一个衍生属性。 * `MobX响应`:并非从observable获取了值,MobX就一定响应,如果是在追踪函数之外和异步回调中使用,MobX将不会做出响应。 “追踪函数” 是 computed 表达式、observer 组件的 render() 方法和when、reaction 和 autorun 的第一个入参函数。 ## 4. Decorators > 装饰器,可使用的装饰器列表 observable.deep observable.ref observable.shallow computed action action.bound 可以使用 @decorator 语法来应用这些装饰器。 [官方文档说明] * **`observable.deep`**: 所有 observable 都使用的默认的装饰器。它可以把任何指定的、非原始数据类型的、非 observable 的值转换成 observable。 * **`observable.ref`**: 禁用自动的 observable 转换,只是创建一个 observable 引用。 * **`observable.shallow`**: 只能与集合组合使用。 将任何分配的集合转换为浅 observable (而不是深 observable)的集合。 换句话说, 集合中的值将不会自动变为 observable。 * **`computed`**: 创建一个衍生属性, 参见 [`computed`](https://cn.mobx.js.org/refguide/computed-decorator.html) * **`action`**: 创建一个动作, 参见 [`action`](https://cn.mobx.js.org/refguide/action.html) * **`action.bound`**: 创建有范围的动作, 参见 [`action`](https://cn.mobx.js.org/refguide/action.html) ## 5. FLOW 创建异步action的一种方式,这里不介绍了。[官网传送](https://cn.mobx.js.org/best/actions.html) # 二、 开启装饰器(Decorators) (1)添加装饰器依赖:babel-plugin-transform-decorators-legacy (2).babelrc文件添加配置 ```python "plugins": ["transform-decorators-legacy"] ``` # 三、三部曲 通过一个小demo,讲述如何使用MobX将应该用变成响应式。 首先必须先添加mobx和mobx-react依赖,装饰器依赖根据用户选择添加。 ## 1. 第一曲 > 定义状态并使其可观察 新建mobx文件夹,observable的相关.js文件存储在此,如下图所示: ![null](//upload-images.jianshu.io/upload_images/10255494-79340cd953f6b073.png?imageMogr2/auto-orient/strip|imageView2/2/w/337/format/webp) image.png 如何定义状态,并使得其可观察呢?接着看代码: counter_store.js(计数): ```python import { observable } from 'mobx' class CounterStore { @observable counter = 0; @observable remoteCounter = 0; constructor(){} increment(){ this.counter++; } decrement(){ this.counter--; } incrementAsync(){ setTimeout(()=>{ this.counter++ },500); } } const counterStore = new CounterStore; export default counterStore; ``` CounterStroe类中,对counter、remoteCounter使用了observable装饰器,即将counter、remoteCounter定义为MobX的状态,并可观察。 虽然increment、decrement、incrementAsync函数前无@action,但是因为没有设置强制action,所以默认被action装饰,都是创建了一个动作。 ## 2. 第二曲 > 创建视图以响应状态的变化 首先使用observer包裹React组件的高级组件: ```python @observer export default class HomeScreen extends Component { ... } ``` 其次,在HomeScreen组件的render方法中,使用被observable转换的值。 ```python import counterStore from '../../mobx/counter_store' render() { return (
Counter Container Test
Clicked:
{`${counterStore.counter}times`}
counterStore.increment()}>| +1 |
counterStore.incrementAsync()}>| +1 Async |
); } } ``` ## 3. 第三曲 > 更改状态 在CounterStore类中,通过action创建了三个动作,分别是increment、decrement、incrementAsync。通过调用action装饰过的函数,实现更改状态的目的。 请看代码,onPress事件中调用函数: ```python import counterStore from '../../mobx/counter_store' render() { return (
Counter Container Test
Clicked:
{`${counterStore.counter}times`}
counterStore.increment()}>| +1 |
counterStore.incrementAsync()}>| +1 Async |
); } } ``` 当点击‘+1’时,上面的次数显示会响应的变化。这就是所谓的副作用一种形式。 # 拓展 如何进行状态的引用呢? 两种方式: > * 全局注册并注入store实例 > * 直接import引用 **全局注册并注入store** 我参考的demo:[https://juejin.im/post/5a3f06cd6fb9a044fe4693bc](https://juejin.im/post/5a3f06cd6fb9a044fe4693bc) demo中使用了Provider进行全局注册并注入Rootstore实例 ```python const Navigation = () => { return (
) } ``` 在需要使用的组件中,使用@inject('rootStore') ,我们就可以愉快地使用 this.props.rootStore 来拿到我们想要的数据啦 ```python @inject('rootStore') @observer export default class HomeScreen extends Component { ... } ``` 注:@observer也需要添加,不然不会随着rootStore属性变化而重新渲染。 **直接import引用** 不进行全局注册,而是在需要使用mobx的Rootstore实例的组件中进行引用即可。 ```python import counterStore from '../../mobx/counter_store' ``` [Github项目demo](https://github.com/boyrt/react-native-mobx) 作者:boyrt 链接:https://www.jianshu.com/p/74698b920a48 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
表情
发送
0
评论