前言
首先简单介绍一下mobx,他和redux类似数据都是单向流动,通过action改变state,促使view更新。主要为了简化组件间数据共享流程&保证唯一数据源。
使用流程
- 定义状态使其可观察
observable
`@observable name = 'zoe';`
`@observable age = '27';`
- 创建
action
,一些改变状态值的动作
@action addAge = () => {
this.age += 1;
};
- 创建视图响应状态变化
@observer
class Store {
@observable name = 'zoe'
@observable age = '27';
@action addAge = () => {
this.age += 1;
};
}
@observer
class Counter extends ReactDOM.Component {
store = new Store();
render() {
return (
<div>
{this.store.age}
<button
onClick={() => {
this.store.addAge();
}}
>
+
</button>
</div>
);
}
}
observable
- 查看通过observable 包装的数据 打印结果
ObservableObjectAdministration
let o=observable({name:'name is zoe'})
console.log({o}) // Proxy {Symbol(mobx administration): ObservableObjectAdministration}
o.name='hello zoe'
console.log(o.name)//name is zoe,除了action外均不能对状态进行更改
- 小结:observable 将我们普通的数据变成可观察的数据,已经不是原来的那个数据类型(例如:从store里取的数组 就需要
toJS(someArray)
转下,否则不能直接用Array的原型上的方法)
山寨 一个observable
思路
- 通过代理Proxy把数据包装成可观察的代理数据
- prox 代理包装过程 要考虑的首要问题是 这个深层嵌套的对象 (用递归 deepProxy)
实现
题外话:ES7的装饰器decorator是依赖于Object.defineProperty
- 装饰器 获取 target数据进行拦截调用包装函数 对其进行数据包装后 返回同名对应的mobx数据
function observable(target, key, descriptor) {
//通过 descriptor.initializer 拿到我们装饰的对象的值 进行包装
if (typeof key === "string") {
let v = descriptor.initializer();
v = createObservableAnnotation(v);
return {
configurable: false,
enumerable: true,
get() {
return v;
},
set(value) {
v = value;
//set的时候 autorun执行,自动更新组件
},
};
}
return createObservableAnnotation(target);
}
- createObservableAnnotation
function createObservableAnnotation(val) {
let handler = () => {
// 连接autorun 用的 ,此处不做深入展开
};
return deepProxy(val, handler);
}
- deepProxy 递归包装深层嵌套的对象
function deepProxy(val,handler) {
// val是基本数据类型,则直接返回
if (typeof val !== "object") return val;
//遍历每一个属性
for (let key in val) {
//递归 实现深层对象的代理
val[key] = deepProxy(val[key], handler);
}
//Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义
return new Proxy(val,handler());
}
小结
今日没有小结 ,中秋快乐