官方解释:
官方文档地址:https://cn.mobx.js.org/refguide/api.html
observable.deep: 所有 observable 都使用的默认的装饰器。它可以把任何指定的、非原始数据类型的、非 observable 的值转换成 observable。
observable.ref: 禁用自动的 observable 转换,只是创建一个 observable 引用。
observable.shallow: 只能与集合组合使用。 将任何分配的集合转换为浅 observable (而不是深 observable)的集合。 换句话说, 集合中的值将不会自动变为 observable。
网上找的解释:
observable: observable.deep 的别名
observable.deep: 任何 observable 都使用的默认的调节器。它将任何(尚未成为 observable )数组,映射或纯对象克隆并转换为 observable 对象,并将其赋值给给定属性
observable.ref: 禁用自动的 observable 转换,只是创建一个 observable 引用
observable.shallow: 只能与集合组合使用。 将任何分配的集合转换为 observable,但该集合的值将按原样处理
observable.struct: 就像 ref, 但会忽略结构上等于当前值的新值
computed: 创建一个衍生属性, 参见 computed
computed(options): 同 computed , 可设置选项
computed.struct: 与 computed 相同,但是只有当视图产生的值与之前的值结构上有不同时,才通知它的观察者
action: 创建一个动作, 参见 action
action(name): 创建一个动作,重载了名称
action.bound: 创建一个动作, 并将 this 绑定到了实例
注:
mobx 通过 enhancer 决定对深层数据结构的处理操作,如 observable.deep 装饰器使用 deepEnhancer 增强器,将数据的深层结构统统转换为 observable 实例(默认操作);observable.shallow 装饰器使用 shallowEnhancer 增强器,只将数据的首层转换为 observable 实例;observable.ref 装饰器使用 referenceEnhancer 增强器,不会将数据转换为 observable 实例(除非新值就是个 observable 实例);
我的理解:*******************************先看代码*******************************************
aa.js代码
import {observable, action, computed} from 'mobx';
class Store {
@observable aa = 'hello';
@observable.deep value = {
v1: 'abc',
v2: true,
v3: 23,
v4: [3, 5, 4],
obj: {
name: 'xh',
age: 18
}
};
@action addValue = () => {
this.value.obj.age ++;
}
@action subValue = () => {
this.value.obj.age --;
}
@computed get getValue() {
return this.value.obj.age * 10;
}
}
app,js代码:
import React, { Component } from 'react';
import './App.module.less';
import Store from './store/aa';
import { observer } from 'mobx-react';
const App = observer(() => {
return(
<div>
<p>{Store.value}</p>
<p>{Store.getValue}</p>
<p>{Store.getTheValue()}</p>
<button onClick={() => Store.addValue()}>增加</button>
<button onClick={() => Store.subValue()}>减少</button>
</div>
);
});
export default App;
界面展示:
通过思考设计模式一的观察者模式:
观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。
我们类比,mobx的@observer 装饰对象后,会把对象转成observable对象,我认的observable对象就是被观察者,界面中我们可能很多地方对这个observable对象的使用,每一处使用的地方我们可以把它想象成观察者,一旦observable对象对象发生改变,那我们的观察者应该马上做出反应,界面上不同使用的地方同时改变。
observable.deep和observable.shallow的区别是什么呢?
拿我们aa.js中的value举例:
如果是observable.shallow,那么v1,v2,v2,v4,obj都会自动被转成observable对象,如果在界面中使用value.v1,value.v2,value.v2,value.v4,value.obj,一旦它们的值被修改,界面上马上变化。注意,此时value.obj.name和value.obj.age并不是observable对象,如果我们在界面中使用value.obj.name和value.obj.age,如果修改它们的值,界面中是不会有任何变化的,依旧是原来的值。如果我们把value比作第一层,obj比作第二层,第一层所有变量会被转化成observable对象,而第二层的变量不会被转成observable对象,也就所说的浅拷贝。
如果是observable.deep(所有 observable 都使用的默认的装饰器),和observable.shallow的区别在于,observable.deep不仅会把第一层所有变量会被转化成observable对象,也会把二层的变量转成observable对象,也就是说value.obj.name和value.obj.age也会变成observable对象,如果界面使用value.obj.name和value.obj.age,它们值被修改后界面也会变化,当然,这里也可以不止两层,可以理解为递归,也就是所说的深拷贝。
observable.ref理解就简单了
import {observable, action, computed} from 'mobx';
class Store {
@observable aa = 'hello';
@observable.deep value = {
v1: 'abc',
v2: true,
v3: 23,
v4: [3, 5, 4],
obj: {
name: 'xh',
age: 18
}
};
@observable.ref ABC = {
a1: 'ge',
a2: true,
obj: {
name: 'xh',
age: 18
}
}
@action addValue = () => {
this.ABC.obj.age ++;
}
@action subValue = () => {
this.ABC.obj.age --;
}
@computed get getValue() {
return this.ABC.obj.age * 10;
}
}
上面这种写法中的ABC不是observable对象,在界面中使用后,再修改值,界面也不会变化。
import {observable, action, computed} from 'mobx';
class Store {
@observable aa = 'hello';
@observable.deep value = {
v1: 'abc',
v2: true,
v3: 23,
v4: [3, 5, 4],
obj: {
name: 'xh',
age: 18
}
};
@observable.ref ABC = this.value
@action addValue = () => {
this.ABC.obj.age ++;
}
@action subValue = () => {
this.ABC.obj.age --;
}
@computed get getValue() {
return this.ABC.obj.age * 10;
}
}
如果像上面这样写的话,界面中使用ABC,调用addValue ()或者subValue ()或者直接修改value的值,界面也会发生改变。
总结一下:observable.ref 装饰器不会将数据转换为 observable 实例(除非新值就是个 observable 实例);