WdBly Blog

懂事、有趣、保持理智

WdBly Blog

懂事、有趣、保持理智

周维 | Jim

603927378@qq.com

MobX + RN

MobX + RN的使用

timg.jpg

基本使用

1.使用@observable 观察数据

通过使用 @observable 装饰器(ES.Next)来给你的类属性添加注解就可以简单地完成这一切。

import { observable } from "mobx"; class Todo { @observable title = ""; @observable list = []; } return new Todo();

2.将类的实例做为props传入至组件使用

// 1. 直接注入组件, 缺点是如果state和组件太多,很混乱 <App state={new Todo()} /> class App extends Component { render(){ return( <div>{this.props.state.title}</div> ) } } // 2. 使用@observer让普通组件变成响应组件 import {observer} from 'mobx-react'; @observer class App extends Component { render() { return <div> <ul> {this.props.state.list.map(todo => <TodoView todo={todo} key={todo.id} /> )} </ul> </div> } } // 装饰器不能修饰函数,这里通过高阶函数处理 const TodoView = observer(({todo}) => <li> <input type="checkbox" checked={todo.finished} onClick={() => todo.finished = !todo.finished} />{todo.title} </li> ) @decorator class A {}; // 等同于 class A {}; A = decorator(A) || A;

observer 是mobx-react提供的Decorator函数, 可以用作包裹 React 组件的高阶组件。 在组件的 render 函数中的任何已使用的 observable 发生变化时,组件都会自动重新渲染。

@符号是ES7的修饰器(Decorator),@符号后的函数是修饰器函数Decorator,修饰器函数可用于修饰类和类的属性和方法

修饰器只能用于类和类的方法,不能用于修饰函数,因为存在函数提升。
由于存在函数提升,使得修饰器不能用于函数。类是不会提升的,所以就没有这方面的问题。

Computed values(计算值)

定义在相关数据发生变化时自动更新的值

import { observable, computed } from "mobx"; class Todo { @observable title = ""; @observable list = []; // list中所有check为ture时返回true @computed get allChecked() { return this.list.every(check => !!check); } // 从 allChecked 中推导出 title @computed set allChecked(value) { this.title = value; } } return new Todo();

当添加了一个新的list对象或者某个list的check属性发生变化时,MobX 会确保allChecked自动更新。

Reactions(反应)

autorun

当使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发。在autorun中使用到的observable值发生改变时才会调用。

import { observable, autorun} from "mobx"; const message = observable({ title: "hello" }) autorun(() => { console.log(message.title, "1") }) autorun(() => { console.log(message, "2") }) message.title = "Hello world" // Hello world 1 // 不会输出 Hello world 2 因为在第二个autorun中并没有 // 直接使用 message.title的值

reaction

reaction接收两个函数,第一个是追踪并返回数据,该数据用作第二个函数,也就是副作用的输入。

reaction比autorun更细粒度,只有reaction第一个参数返回的observable值才会被监控,且第一次运行不会执行sideEffect方法。支持防抖

import { observable, reaction} from "mobx"; const message = observable({ title: "hello" }) reaction(() => data, data => { sideEffect }, options)

Action(动作)

任何应用都有动作。动作是任何用来修改状态的东西。
使用MobX你可以在代码中显式地标记出动作所在的位置。 动作可以有助于更好的组织代码。 建议在任何更改 observable 或者有副作用的函数上使用动作。

严格模式更改 observable则必须在action中执行。

class Todo { @observable title = ""; @observable list = []; @action switchValue = async id => { this.title = "title"; } }

inject (mobx-react)

相当于Provider 的高阶组件。可以用来从 React 的context中挑选 store 作为 prop 传递给目标组件。用法:

@inject("store1", "store2") @observer class App extends Component { ... }

extendObservable

extendObservable(target, properties, decorators?, options?)

ExtendObservable 用来向已存在的目标对象添加 observable 属性。 属性映射中的所有键值对都会导致目标上的新的 observable 属性被初始化为给定值。 属性映射中的任意 getters 都会转化成计算属性。

class Todo { // a,b属性都会被观察 @observable obj = { a: 1, b: 2 }; @action modifyObj = () => { // c属性不可被观察 this.obj.c = 3; } } // 解决方案extendObservable extendObservable(this, { c: 3 })

Observable观察者

MobX 追踪属性访问,而不是值, MobX观察属性的引用是否发生变化

image.png

Object

如果把一个普通的 JavaScript 对象传递给 observable 方法,对象的所有属性都将被拷贝至一个克隆对象并将克隆对象转变成可观察的。

普通对象是指不是使用构造函数创建出来的对象,而是以 Object 作为其原型,或者根本没有原型。

Array

数组中的所有(未来的)值都会是可观察的

除了数组内置的一些方法,被观察的数组还可以有以下方法:

intercept(interceptor) - 可以用来在任何变化作用于数组前将其拦截。参见 observe & intercept
observe(listener, fireImmediately? = false) - 监听数组的变化。回调函数将接收表示数组拼接或数组更改的参数,它符合 ES7 提议。它返回一个清理函数以用来停止监听器。
clear() - 从数组中删除所有项。
replace(newItems) - 用新项替换数组中所有已存在的项。
find(predicate: (item, index, array) => boolean, thisArg?) - 基本上等同于 ES7 的 Array.find 提议。
findIndex(predicate: (item, index, array) => boolean, thisArg?) - 基本上等同于 ES7 的 Array.findIndex 提议。
remove(value) - 通过值从数组中移除一个单个的项。如果项被找到并移除的话,返回 true 。
[MobX 4 及以下版本] peek() - 和 slice() 类似, 返回一个有所有值的数组并且数组可以放心的传递给其它库。
不同于 sort 和 reverse 函数的内置实现,observableArray.sort 和 observableArray.reverse 不会改变数组本身,而只是返回一个排序过/反转过的拷贝。在 MobX 5 及以上版本中会出现警告。推荐使用 array.slice().sort() 来替代。