MobX实际上是一个比较轻便的可扩展的状态管理工具,是一个由Facebook以及一些其余团队的人共同维护的开源项目。 当应用公共状态的组件在状态发生变化的时候,会自动完成与状态相关的全部事情,例如自动更新View,自动缓存数据,自动通知server等。 例如React的体系,react + redux + react-redux + redux-saga, view层触发一个action,中间件会将这个动做进行dispatch,而后reducer执行相应的更新状态方法,使得store的状态更新。 MobX官方推荐与React搭配使用,来存储和更新应用状态,因此最好搭配mobx-react中间件使用: 原理: 一、React的render是将存储的状态转化为树状结构来渲染组件的方法; Mobx是用来存储和更新状态的工具; 二、React使用的方法是采用虚拟Dom来进行view视图的缓存,来减小繁琐的Dom更新 而Mobx则经过一个虚拟的状态依赖图表来让react组件和应用状态同步化来减小没必要要的状态来更新组件的
一、对比Redux conponent-->dispatch(action)-->reducer-->subscribe-->getState-->component 对比React-Redux component-->actionCreator(data)-->reducer-->component 这里的reducer在MobX里都给了action,直接经过action来更改状态,不须要reducer来操做state了,也不需关注reducer纯不纯了 二、对比Vuex component-->dispatch(action)-->mutation--(mutate)-->state-->component vuex中提出了同步mutation和异步action,如今mobx也无需mutaiton,但借鉴了computed这个纯函数。 相比这两个工具,MobX内置了数据变化监听机制,使得在实际应用的时候一切都是那么的顺其天然。
MobX的数据驱动解构: action--(update)-->state--(update)-->computed--(trigger)-->reaction MobX与decorater语法结合(注解形式@)结合起来用比较优雅,也算是MobX的一大亮点吧!
是被观察着和观察者的概念,你也能够理解为生产者和消费者的概念 @observable/Observable 方法将对象的全部属性从新克隆成新对象,并将克隆对象转变成可观察的。 @observer就是在你订阅观察的对象的地方添加注释来监听对象的更新 Observable 方法的值能够是以下类型: 一、object(原型是Object): Observable方法将该对象克隆成新对象并将属性转变成可观察的; 可是后添加的属性不会变为可观察的,须要用到set或者extendObservable; eg: @observable car = {color: red; name: 'Infinity'} 注:这也实际上是extendObservable(this,{ car: {color: red; name: 'Infinity'} })的语法糖 向对象中添加属性: extendObservable(car, {price: '300w'}) 二、Array:Observable会建立一个类数组对象来代替真正的数组,而且支持全部的原生方法, 可是sort和reverse有所不一样,这里的被观察的数组对象的这两个方法,是不会改变数组自己,而是一个拷贝的数组; 三、Es6的Map:建立一个动态建的observable映射,能够对特定项的更改作出反应等;会返回一个新的Observable Map 四、object(有自身的原型对象):这种状况须要使用observable.box(value)来管理这样的值 经过box这个箱子来存这些值,并使用.get()用来获取当前值,采用.set(newValue)来更新值。 eg: const carName = observable.box('Infinity'); console.log(carName.get()); carName.set('ofo');
是在定义相关的一些数据发生变化的时候自动更新的值,经过@computed来修饰使用; 注意:computed修饰的是一个状态,状态不能重复声明,只有参与计算的值发生改变才会触发computed 例如我须要对数组进行筛选: @observable numbersArr = [99, 80, 79, 68, 2, 43, 1, 23]; 1、getter eg: // 筛选数组中乘2并大于50的数 @computed get computedNumbers() { return this.numbersArr.filter((item) => { return item * 2 > 50; }).join(' '); } 而后在组件内进行调用: <div>{this.props.store.computedNumbers}</div> 2、setter set computedBumbers(value) { this.numbersArr = [99, 80, 79, 68, 2, 43, 1, 23]; } // set方式可使得数据进行逆推导 将数据按照既定的方式进行复原 eg: @observable length = 2; @computed get squared() { return this.length * this.length; } set squared(value) { this.length = Math.sqrt(value); } 注:这与autorun还有点区别,若是有一个函数应该自动运行(例如只是为了达到某种效果/功能),但不会产生一个新的值,那就使用autorun,可是通常这种状况比较少
比起官方说的“动做”,我更愿意称为是“行为”,mobx的action吸取了redux和vuex的数据处理的复杂逻辑 用来修改状态,不一样于Computed eg: component: sendInfo = () => { const username = this.name.value; const pwd = this.pwd.value; if (!username || !pwd) { return; } // 调接口 this.props.testDecStore.handleGetUserInfo(); }; store: // 4、异步数据获取 @action handleGetUserInfo() { this.sendCount++; testDecService.getUserInfo().then((data) => { this.userInfo = data; }) }
这个函数相似computed,是经过对状态的更新作出反应,可是不一样于computed。 computed建立的函数,是有本身的观察者的,而autorun是只有它的依赖关系改变时才会从新计算, 不然它的值被认为是不相干的。正如官方所说是比较适合log打印日志,持久化更新UI的代码,而不是用来产生新的值 接收的参数: 1,对象, 二、delay: 函数延迟执行时间,例如节流去抖 三、name: 四、onError: 用来处理reaction的错误 五、scheduler: 设置自定义调度器以决定如何调度autorun函数的从新运行 eg: autorun(() => { // do something }, { onError(e) { alert('error') } }) 实例: autorun(() => { this.myname = `my name is ${this.firstName} ${this.lastName}`; }); changeName = () => { this.firstName = `Alice${new Date().getTime()}`; this.lastName = `Thomas${new Date().getTime()}`; }; <div className="tips" > 测试autorun <span className="btn-span" onClick={this.changeName}>开始</span> <div>{this.myname}</div> </div> 只要firstname和lastname发生变化都会更新dom
可是,若是仅仅想要在被观察的变量有变化的时候触发,而不是当即执行autorun,那么咱们能够用到reaction了;vue
Reaction是在初次数据变化后才会触发
是mobx-react包单独提供的 Observer是用来将React组建转变成响应式的组件,内部经过mobx.autorun包装了组件的 render函数,来确保store的数据更新时来刷新组件 @observer 是observer(class ***{})的注解形式,用来观察组件, 高阶组件 @observer class Test extends React.Component{} 无状态组件 const Test = observer(() => <div>test</div>) 使用inject组件链接提供的sotres,他会使得stores能够做为组件的props调用 eg: @inject('testStore') @observer class Test extends React.Component{}
Provider函数为connect函数提供store参数,自己connect函数就是用来链接视图和数据层的方法。 在跟组件外层包一层provider,使得全部的子组件默认均可以拿到state 使用: import { Provider } from 'mobx-react'; import store from '../stores'; <Provider {...store}> ... </Provider>
引入数据的方式,@inject(stores); 使得数据被自动保存在组件的this.props中
mobx-react新增的生命周期钩子,当组件从新render的时候会被触发,但在初始渲染前是不会被触发的
mobx-react提供的错误钩子函数来收集错误 用法: import { onError } from 'mobx-react'; onError((error) => { consol.log(error); })