推荐版本: "mobx-react": "4.1.0", "mobx": "^2.7.0 || ^3.0.0"react
能够任何数据结构来存储状态,如对象、数组、类,打上mobx的标记会变为可观察。git
import { observable } from 'mobx'; var appStore = observable({ timer: 0; });
mobx 以最小限度更新视图,任何函数均可以成为响应式视图观察自身数据。 github
import {observer} from 'mobx-react'; @observer class TimerView extends React.Component { render() { return ( <button onClick={this.onReset.bind(this)}> Seconds passed: {this.props.appState.timer} </button> ); } onReset() { this.props.appState.resetTimer(); } }; ReactDOM.render(<TimerView appState={appStore} />, document.body);
mobx会用简单直观的方式更改状态,使用action(能够配置Mobx强制使用action更新)或者直接修改web
状态是驱动应用的数据。像待办事务列表的特定状态,还有像当前已选元素的视图状态。
状态就像有数据的 Excel表格。算法
什么是衍生, 源自状态而且不会再有进一步的相互做用的东西就是衍生。 express
使用纯函数从当前可观察状态中衍生出的值。 编程
是当 State 改变时须要自动发生的反作用。。须要有一个桥梁连接 函数式编程 和 响应式编程
初次使用mobx会常用reactions,可是推荐使用computed,回到表格的概念,公式是计算值的衍生。 redux
动做 任意一段能够改变状态的代码。 用户操做,后端数据推送,预约事件等。
动做 相似在表格单元格中输入一个新值。 mobx中能够显示的定义动做,@action . 后端
mobx支持单向的数据流,动做来改变状态,从而 状态State 的改变会更新受影响的视图。
action ---> state ---> view
当 State 改变时,全部衍生都会进行原子级自动更新 所以不可能观察到中间值
所有的 衍生 默认都是同步更新 所以在动做以后,能够安全的检查计算值
计算值 是延迟更新的。 任何不在使用状态的计算值都不会更新,直到须要时会进行 反作用(IO),不使用时会自动垃圾回收
计算值 不该该去改变状态,应该是一个纯洁的反作用。 api
主要api: Computed 、 observable 、 reactions 、 actions
observable(value); @observable property = value;
Observable 观察的值能够是基本类型、引用类型、普通对象、类实例、数组和映射。
主要类型转换规则,或者经过装饰器微调(修饰class,函数)
可用装饰的列表是这些:
class TodoList { todos = {} get unfinishedTodoCount() { return values(this.todos).filter(todo => !todo.finished).length } addTodo() { const t = new Todo() t.title = 'Test_' + Math.random() set(this.todos, t.id, t) } } decorate(TodoList, { todos: observable, unfinishedTodoCount: computed, addTodo: action.bound }) // 对类 Observable 转换
用法好几种,看起来只有一些细微的差异:
Computed 自带不少操做属性 控制 Computed 行为
任何用来 修改状态 的东西
建议在任何更改 observable 或者有反作用的函数上进行 Actions修饰
flow(function* (args) {})
flow() 接收 generator 函数做为他的惟一输入
flow 的关键做用是 处理异步代码时确保代码被action包装 ,由于正常的 observable state 对异步操做没法经过 enforceActions 检查。
神奇的flow能够解决这个异步不跟踪的问题
注意,异步函数必须是 generator ,并且在内部只能 yield promises
import { configure, flow } from 'mobx'; // 不容许在动做外部修改状态 严格模式的意思 configure({ enforceActions: true }); class Store { @observable githubProjects = []; @observable state = "pending"; // "pending" / "done" / "error" fetchProjects = flow(function* fetchProjects() { // <- 注意*号,这是生成器函数! this.githubProjects = []; this.state = "pending"; try { const projects = yield someAsyncProcess(); // 用 yield 代替 await const filteredProjects = somePreprocessing(projects); // 异步代码自动会被 `action` 包装 this.state = "done"; this.githubProjects = filteredProjects; } catch (error) { this.state = "error"; } }) }
Flows 能够撤销,调用promise的cancel() 方法会中止异步状态取值, 会继续执行 finally 子句 。
计算值是能够根据现有的状态或其余计算值衍生的值。
概念上来说,他们和表格中的值十分类似,好比汇总80分以上的同窗。
计算属性 可使实际可修改的值尽量的小,计算属性也是高度优化过的,能够多用
声明式的建立计算属性,能够在类任意的属性上使用装饰器
import { observable, computed } from 'mobx'; class orderline { @observable price = 10; @observable amount = 1; constructor(price) { this.price = price; } @computed get total() { return this.price * this.amount; } }
import { observable, autorun } from 'mobx'; const value = observable(0); const number = observable(100); autorun(() => { console.log(value.get()); }); value.set(1); value.set(2); number.set(101); // 0 1 2 不打印 101 yinwei number 未在autorun内部执行 number.get()/
Mobx 学习 基本写法 * 此处声明式的监控变量,与 ES6 的类修饰不一样。
import { observable, action, computed, toJS } from 'mobx' import { observer } from 'mobx-react'
export default class InstanceStore { @observable value = 1
@action modifyValue(v) { this.value = v } @computed get getValue() { return this.value * 10; }
}
computed 直接获取一个计算后的值。
若是一个值须要根据某个state计算,而且也须要被观察则可使用 @computed autorun 相似
autorun 用于执行一些和值变化有关的操做,好比异步请求,数据处理等
computed 用于根据已有的值,计算出新的值返回一个对观察值追踪的结果 var ins = new InstanceStore(); console.log('value form mobx computed', toJS(ins.getValue()))
autorun 在不须要继续使用的状况能够进行垃圾回收
var numbers = observable([1,2,3]);
var sum = computed(() => numbers.reduce((a, b) => a + b, 0));
var disposer = autorun(() => console.log(sum.get())); // '6'
numbers.push(4); // '10'
disposer();
numbers.push(5); // 什么也不打印,由于disposer执行是再也不对autorun reaction
过时状态值方式以下
var ins = new InstanceStore();
console.log(toJS(ins.value),'get value from mobx');
dispatch 修改值 var ins = new InstanceStore(); ins.modifyValue(1000);
在组件内可使用观察者模式 @observer class routeCreate extends Component { constructor(props) { super(props); this.store = new InstanceStore(); } ... }
使用 observer 修饰组件,而且在render内部有 mobx 值的引用,组件会多一个生命周期 componentWillReact // redux 改变值的方式是经过拷贝原来的对象生成新的对象,触发组件的componentWillReceiveProps // mobx 是以原始值的基础上生成新的对象,以前的引用不变因此mobx 不会触发ReceiveProps周期
异步处理
mobx 状态值为同步更新。
export default class InstanceStore { @observable value = 1
@action modifyValue(v) { this.value = v; setTimeout(this.valueAdd, 100); } @action.bound valueAdd(v) { this.value = v + 20; }
}
// .bound 是js执行环境语法糖 // 过多action ? 须要简化写法 // mobx 自身提供了一个工具函数帮助跟新对应action中的值 runInAction
export default class InstanceStore {
@observable value = 1
@action asyncModifyValue(v) { this.value = v; setTimeout(action('valueAdd', () => { this.value = v + 20 }), 100); } @action asyncModify(v) { this.value = v; setTimeout(runInAction(() => { this.value = v + 20 }), 100); }
}
// 异步action,action能够这样写
@asyncAction changeValue() { this.value = 0; const data = yield Promise.resolve(1) this.value = data; }
toJS 将mobx state 序列转换为js可识别类型? 更新action的约束 mobx 非强制使用action改变state;若是要增强制action触发state能够经过 Mobx.configure({enforceActions: true}) 加限制条件,强制经过action更新,适用于大型项目 如下是遗留问题 * 1, mobx 是不是同步更新 是 * 2, mobx toJS是如何实现的 * 3,store对应单个变量,会按照类型预留数组空间,是什么缘由 * 4,使用toJS获取数据,须要在class名称上面加 @observer 吗 * 5,为何mobx取值,是如此的简介?,并且是支持多状态 * 6,extendObservable 能够按照扩展的方式 装饰函数或class里的对象