【前端丛林】React这样服用,效果更佳(12)

109 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

前言

哈喽大家好,我是Lotzinfly,一位前端小猎人。欢迎大家再次来到前端丛林,在这里你将会遇到各种各样的前端猎物,我希望可以把这些前端猎物统统拿下,嚼碎了服用,并成为自己身上的骨肉。今天是我们冒险的第十二天,昨天给大家简单介绍了一下mobx,让大家有了一个初步的概念,今天会深入mobx探寻其中的奥秘。话不多说,开始我们的冒险之旅吧!

1.mobx

1.1 observable

  • MobX为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。
  • observable 就是一种让数据的变化可以被观察的方法
  • 先把数据转化成可以被观察的对象,那么对这些数据的修改就可以被监视

1.1.1 引用类型 (observable)

const { observable, isArrayLike } = require('mobx');
function observable2(target) {
    return new Proxy(target, {});
}
const p1 = observable2({ name: '小明' });
console.log(p1.name);
const { observable } = require('mobx');
function observable2(target) {
    return new Proxy(target, {
    });
}
const p1 = observable([1, 2, 3]);
p1.push(4);
p1.pop();
console.log(p1);
console.log(Array.isArray(p1));

1.1.2 基本类型(observable.box)

image.png

const { observable } = require('mobx');
let num = observable.box(10);
let str = observable.box('hello');
let bool = observable.box(true);
console.log(num.get(), str.get(), bool.get());
num.set(100);
str.set('world');
bool.set(false);
console.log(num.get(), str.get(), bool.get());

1.1.3 decorator

import { observable } from 'mobx';
class Store {
    @observable name = '小明';
    @observable age = 18;
    @observable isMarried = false;
    @observable hobbies = [];
    @observable home = { name: '广州' };
    @observable skills = new Map();
}

2.使用对可观察对象做出响应

2.1 computed

  • 计算值(computed values)是可以根据现有的状态或其它计算值衍生出的值
  • 组合已有的可观察数据,成为新的可观察数据
  • 既是反应又是可观察数据
  • 可以作为函数使用也可以作为decorator使用
  • 使用 .get() 来获取计算的当前值
  • 使用 .observe(callback) 来观察值的改变
  • computed值可以引用其它computed的值,但是不能循环引用
let { observable, computed } = require('mobx');
class Store {
    @observable name = '小明';
    @observable age = 18;
    @observable area = '020';
    @observable number = "13712345678"
    @observable province = "广东";
    @observable city = "广州";
    @computed get home() {
        return this.province + this.city;
    }
}
let store = new Store();
let cell = computed(function () {
    return store.area + '-' + store.number;
});
cell.observe(change => console.log(change));
console.log(cell.get());
store.area = '020';
store.number = '13112345678';
console.log(cell.get());
console.log(store.home);
store.province = '山东';
store.city = '济南';
console.log(store.home);

2.2 autorun

  • 如果使用修饰器模式,则不能再用observe方法了
  • 当你想创建一个响应式函数,而该函数本身永远不会有观察者时,可以使用 mobx.autorun
  • 当使用 autorun 时,所提供的函数总是立即被触发一次,然后每次它的依赖关系改变时会再次被触发
  • 数据渲染后自动渲染
autorun(() => {
    //console.log(store.province,store.city);
    console.log(store.home);
});
store.province = '江苏';
store.city = '南京';

2.3 when

  • when 观察并运行给定的 predicate ,直到返回true
  • 一旦返回 true,给定的 effect 就会被执行,然后 autorunner(自动运行程序) 会被清理
  • 该函数返回一个清理器以提前取消自动运行程序
when(predicate: () => boolean, effect?: () => void, options?)
let dispose = when(() => store.age >= 18, () => {
    console.log('你已经成年了!')
});
dispose();
store.age = 10;
store.age = 20;
store.age = 30;

2.4 reaction

  • autorun 的变种, autorun 会自动触发, reaction 对于如何追踪 observable 赋予了更细粒度的控制
  • 它接收两个函数参数,第一个(数据 函数)是用来追踪并返回数据作为第二个函数(效果 函数)的输入
  • 不同于 autorun 的是当创建时效果 函数不会直接运行,只有在数据表达式首次返回一个新值后才会运行
  • 可以用在登录信息存储和写缓存逻辑
reaction(() => [store.province, store.city], arr => console.log(arr.join(',')));
store.province = '广东';
store.city = '广州';

3.action

  • 前面的方式每次修改都会触发 autorun 和 reaction 执行
  • 用户一次操作需要修改多个变量,但是视图更新只需要一次
  • 任何应用都有动作,动作是任何用来修改状态的东西
  • 动作会分批处理变化并只在(最外层的)动作完成后通知计算值和反应
  • 这将确保在动作完成之前,在动作期间生成的中间值或未完成的值对应用的其余部分是不可见的

3.1 action

let { observable, computed, autorun, when, reaction, action } = require('mobx');
class Store {
    @observable province = "广东";
    @observable city = "东莞";
    @action moveHome(province, city) {
        this.province = province;
        this.city = city;
    }
}
let store = new Store();
reaction(() => [store.province, store.city], arr => console.log(arr.join(',')));
store.moveHome('山东', '济南');

3.2 action.bound

let { observable, computed, autorun, when, reaction, action } = require('mobx');
class Store {
    @observable province = "广东";
    @observable city = "东莞";
    @action.bound moveHome(province, city) {
        this.province = province;
        this.city = city;
    }
}
let store = new Store();
reaction(() => [store.province, store.city], arr => console.log(arr.join(',')));
let moveHome=store.moveHome;
moveHome('山东','济南');

3.3 runInAction

runInAction(() => {
  store.province='山东';
  store.city='济南';
});

结尾

好啦,这期的前端丛林大冒险先到这里啦!这期我们深入了解了mobx,下期我们来介绍一下它的应用。大家一定要好好啃下来嚼烂嚼透。希望大家可以好好品尝并消化,迅速升级,接下来我们才更好地过五关斩六将!好啦,我们下期再见。拜拜!