observable.deep和observable.ref和observable.shallow区别

官方解释:

官方文档地址: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 实例);

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值