mobx入门

623 阅读3分钟

mobx是什么

mobx是简单、可扩展的状态数据管理工具。基于响应式编程思想,核心为状态变化引起的副作用应该被自动触发。应用程序逻辑只需要修改状态数据即可,mobx会自动触发切缓存渲染UI等业务定义的副作用,无需人工干预。解耦UI渲染和数据业务逻辑

mobx和redux对比:开发难度低、开发代码量少、渲染性能好。

class和decorator

class具有继承、多态功能。实现Dog继承Animal

//es5实现继承的方式
function Animal(){}
function Dog(){}

Object.defineProperties(Animal.prototype, {
    name: {
        value(){
            return 'Animal'
        }
    },
    say: {
        value(){
            return `I am ${this.name()}`
        }
    }
});
//多态:子类覆盖父类的方法
Dog.prototype = Object.create(Animal.prototype, {
    constructor: {
        value: Dog,
        enumerable: false
    },
    name: {
        value(){
            return "Dog"
        }
    }
});

 dog instanceof Animal
 dog.__proto__.__proto__... == Animal.prototype
 dog.__proto__ == Dog.prototype
 Dog.prototype.__proto__... === Animal.prototype

//es6中实现继承
class Animal{
    name(){
        return 'Animal';
    }
    say(){
        return `I am ${this.name()}`
    }
}
class Dog extends Animal{
    foo='foo';
    name(){
        return 'Dog';
    }
}

console.log(new Dog() instanceof Animal);

decorator是修饰器,在声明阶段实现类与类成员注解的一种语法

//类的decorator
function log(target){
    const desc = Object.getOwnPropertyDescriptors(target.prototype);
    for(let key of Object.keys(desc)){
        if(key === 'constructor'){
            continue;
        }
        const func = desc[key].value;
        if (typeof func === 'function'){
            Object.defineProperty(target.prototype, key, {
                value(...args){
                    console.log('brefor ', key);
                    const res = func.apply(this, args);
                    console.log('after ', key);
                    return res;
                }
            })
        }
    }
}
//类属性的decorator
function readonly(target, key, descriptor){
    descriptor.writable = false;
}
//类方法的decorator
function validate(target, key, descriptor){
    const func = descriptor.value;
    descriptor.value = function(...args){
        for (let num of args) {
            if(typeof num != 'number'){
                throw new Error(`${num} is not number`);
            }
        }
        return func.apply(this, args);
    }
}

@log
class Numberis{
    @readonly PI = 3.14;

    @validate
    sum(...args){
        return args.reduce((s, c)=> s + c, 0);
    }
}

//new Numberis().PI = 1000;
console.log(new Numberis().sum(23, 'xxx'));

mobx 常用API

  • 1、可观察的数据(observable)

observable是一种让数据的变化可以被观察的方法。原始数据类型:string、number、boolean、symbol。复杂数据类型:对象、数组、map

import { observable, isArrayLike,isObservableObject, extendObservable} from 'mobx';

//observable  Proxy、ObservableMap
const arr = observable([1,2,3]);
const obj = observable({a: 'a'});
const map = observable(new Map());

//observable.box   ObservableValue类型
const num = observable.box(1);
const str = observable.box('aaa');
const bool = observable.box(true);
//获取原始值通过get,修改原始值set
console.log(num.get(), str, bool.get())

//封装后直接使用@observable就可以修饰不同类型的值
class Store {
    @observable array = [1,2,3];
    @observable object = {a: 'aaa'};
    @observable map = new Map();

    @observable num = 122;
    @observable str = 'aaaa';
    @observable bool = false;
}
  • 2、对可观察对象作出反应,监听变量的更改

常用API有computed、autorun、when、reaction

import { observable, computed, autorun, when, reaction, action, runInAction } from 'mobx';
class Store {
    @observable array = [1,2,3];
    @observable object = {a: 'aaa'};
    @observable map = new Map();

    @observable num = 122;
    @observable str = 'aaaa';
    @observable bool = false;
    
     @computed get mixed(){
        return store.str + '/' + store.num;
    }
}

const  store = new Store();

//computed 将可观察数据组合起来变成一个新的可观察数据
const foo = computed(function(){
     return store.str + '/' + store.num;
});
foo.get();
foo.observe(function(change){
     console.log(change);
});

//autorun 修改可观察数据就会执行,如下为str、num
autorun(function(){ 
     console.log(store.mixed);
})

//when 第一个参数必须根据可观察数据返回boolean值,为真执行第二个函数
when(()=> {
     return store.bool;
}, ()=> {
     console.log('this is true');
})

//reaction 应用场景:在没有数据之前不想,也没有必要调用写缓存的逻辑
reaction(()=> [store.num, store.str], (arr)=> {
    console.log(arr);
})
  • 3、修改可观察数据action

数据的赋值每次都会触发autorun、reaction,这样会带来严重的浪费。多数情况下,同步修改n个变量,只希望变更一次视图。所以引入action,多次对状态的赋值合并成一次,从而减少触发autorun、reaction的次数

class Store{
	...
    @action 
    bar(){
        this.num = 4343;
        this.str = 'bbbb';
    }
    @action.bound
    foo(){
        this.num = 4343;
        this.str = 'bbbb';
    }
}
const  store = new Store();

//action
store.bar();

//action.bound
var foo = store.foo;
foo();

//runInAction
runInAction('modify', ()=>{
    store.num = 4343;
    store.str = 'bbbb';
})

mobx的应用

mobx-react是mobx和react之间的桥梁,将react组件转换成对可观察数据的反应,准确的讲是将react的render方法包装成autorun

利用mobx-react工具库让mobx维护react项目状态。解耦业务逻辑和视图渲染

  • 1、将react中的用户行为转换成action
  • 2、将数据绑定到react组件上以驱动视图

mobx常用工具函数

observe、toJS、trace、spy

  • 尽可能晚的取出可观察数据的值
  • 尽可能细的拆分视图组件
  • 使用专用组件处理列表

参考链接