mobx 入门
observable(可观察的数据)
数组
import { observable, isArrayLike } from 'mobx' const arr = observable(['a', 'b', 'c']); // 观察之后,数组将不是真正的数组,而是一个Observable数组 console.log(arr, Array.isArray(arr), isArrayLike(arr); // ObservableArray false true // 但是可以依然像数组一样操作数据 console.log(arr[0]); // a console.log(arr.pop()) // c
对象
const obj = observable({a: 1, b:2}); // 返回的也不是纯对象,而是一个被转化的可被观察的对象 console.log(obj) //ObservableObjectAdministration // 同样也可以直接对该对象进行读取 console.log(obj.a, obj.b) // 1 2 // TODU: mobx只能对已有的属性进行监视,so,在初始化的时候添加可被监视的属性,如果有倔脾气的童鞋,我就要新添加的属性进行监视,你能不能行?笑话,男人怎么能被说不行呢。如果要调用新添加的属性呢,使用extendObservable()
Map集合
const map = observable(new Map()); // 同样也是转化之后的,可被观察的map console.log(map) //ObservableMap // 同样也可以直接调用map方法 map.set('a', 1); console.log(map.has('a')); // true map.delete('a'); console.log(map.has('a')); // false
Number、String、Boolean
// Number、String、Boolean原始数据类型需要用observable.box()来包装可被观察的变量。 var num = observable.box(20) var str = observable.box('hello') var bool = observable.box(true) console.log(num, str, bool); // 三个都是可被观察的ObservableValue类型 // 如果要用到原始类型值,需要用observable.get() console.log(num.get(), str.get(), bool.get()) // 20 'hello' true // 如果想要修改原始类型值,需要用observable.set() num.set(50); str.set('world'); bool.set(false); console.log(num.get(), str.get(), bool.get()) // 50 'world' false
使用修饰器
class Store { @observable array = []; @observable obj = {}; @observable map = new Map(); // 敏感的童鞋可能会问了,诶,不是说原始数据类型用什么box还有get、set么,因为mobx为了简化Api,在修饰器observable里做了数据类型判断。 @observable string = 'hello'; @observable number = 20; @observable bool = false; }
观察数据变化的方式
computed
// 首先引入computed import { observable, isArrayLike, computed } from 'mobx'; // 用法1 var store = new Store(); var foo = computed(function() { // 拼接被观察的两个数据 return store.string + '/' + store.number; }); // 当数据改变时,调用此方法 foo.observe(function(change) { // change代表当前改变的变量值 console.log(change); }); // 当修改可观察数据时,会触发foo.observe store.string = 'world' store.number = 30 console.log(foo); // observableValue类型 console.log(foo.get()); // 拼接后的字符串 // 用法2,在store里直接用修饰器语法使用 class Store { @observable array = []; @observable obj = {}; @observable map = new Map(); @observable string = 'hello'; @observable number = 20; @observable bool = false; // 通过这个方法,只能得到最终的计算值,不能获取observe的方法了 @computed get mixed() { return store.string + '/' + store.number; } }
autorun
// 引用autorun import { observable, isArrayLike, computed, autorun } from 'mobx'; // 初始化会自动运行,修改autorun中任意可观察数据可触发aoturun autorun(() => { console.log(store.string + '/' + store.number); // hello/20 }); store.string = 'world'; // world/20 store.number = 30; // world/30
when
// 引入when import { observable, isArrayLike, computed, autorun, when } from 'mobx'; // when 接收两个函数,第一个为布尔值,当只有第一个为true的时候,才会执行第二个函数,并且保证最多只被执行一次。 // TUDU: 第一个参数为布尔值,必须是一个可观察数据,不能根据普通变量 // TUDO: 如果一开始就返回真,那么第二个函数会同步立即执行 when(() => store.bool, () => console.log("it's true")); store.bool = true; // "it's true"
reaction
// 引入reaction import { observable, isArrayLike, computed, autorun, when, reaction } from 'mobx'; // 当引入的可观察数据发生变化时,触发第二个函数 reaction(() => [store.string, store.number], arr => console.log(arr.join('/'))); store.string = 'world'; // world/20 store.number = 30; // world/30
action
// 引入action import { observable, isArrayLike, computed, autorun, when, reaction, action } from 'mobx'; class Store { @observable array = []; @observable obj = {}; @observable map = new Map(); @observable string = 'hello'; @observable number = 20; @observable bool = false; @action bar() { this.string = 'world'; this.number = 30; } } reaction(() => [store.string, store.number], arr => console.log(arr.join('/'))); // 在action里修改,这样reaction只被触发了一次,提高性能 store.bar(); // world/30 // 使用runInAction方法,同样只会触发一次 runInAction(() => { store.string = 'world'; store.number = 30; })
mobx-react
PropTypes
// react的PropTypes可以限制参数的类型,但是可观察数据类型不是原始类型,所以需要使用mobx-react的PropTypes // 引入PropTypes 更改名称,防止和react PropTypes重名 import { PropTypes as ObservablePropTypes } from 'mobx-react' action propTypes = { array: ObservablePropTypes.observableArray }
observer
// 引入observer import {observer, PropTypes as ObservablePropTypes } from 'mobx-react' // 不同于observable修饰器,它不是修饰类成员的,而是修饰类本身的(react组件类。谁真正的用到了被修改的可观察数据,谁修重渲染,谁就被observer修饰) @observer class Bar extends Conponent { static propTypes = { array: ObservablePropTypes.observableArray }; render() { const array = this.props.array; return <div>{array.length}</div> } }
常用工具函数
toJS
var obj =observable({ x: 1 }); var clone = toJS(obj); // isObservableObject 判断是否是observable对象 console.log(isObservableObject(obj)); // true console.log(isObservableObject(clone)); // false
observe
// 引入observe import { observe, observable, isArrayLike, computed, autorun, when, reaction, action } from 'mobx'; // 纯函数,用于监听被观察数据发生变化 constructor() { // 每次this.list列表发生变化的时候都会触发回调函数 observe(this.list, change => { console.log(change) }) }
spy
// 用于监控所有事件 对可观察数据的每次修改, 对autorun、reaction的每次触发 spy(event => { console.log(event) // 每次都会调用,如果不限制会浪费性能 })