核心概念

这里在一定程度上参考了Vuex的文档,所以在一定程度上Tms合Vuex是十分相似的,不同的是Tms没有Vuex的Commit => Mutation的概念,而是只有Commit

State

class Count extends Tms {
    value: number = 0;
    $setValue(value: number) {
        this.value = value;
    }
}

const count = new Count();
count.value; // => 0

在Tms中,每一个实例的可枚举属性,都被视为一个状态。你可以随意的读取实例的状态,但是不能随意的更改的实例的状态,否则导致实例的状态无法追踪。 切记:所有更新实例状态,都需要通过Commit方法来进行更改,这样才能对实例状态变化的过程进行追踪。

😊 正确的写法,实例状态的变化,会变得可追踪

count.$setValue(1000);

😢 这是一种错误的写法,实例状态的变化,会变得无法追踪。

count.value = 1000;

Getter

class Count extends Tms {
    value: number = 0;
    get valueText (): string {
        return `当前的value值是:${this.value}`;
    }
}

如果在程序中,有很多地方都需要同样的数据,使用Getter可以让我们的程序得到更好的优化。

Commit

Action

Action专门负责所有的异步操作、比如定时器、HTTP请求等,它不负责更新状态,它将请求的结果提交给Commit方法。

😊 正确的:一个HTTP请求查询的例子

interface Response {
    code: number;
    data: string [];
}

class Api {
    getList(): Promise<Response> {
        return new Promise((resolve) => {
            resolve({
                code: 0,
                data: ['1', '2']
            });
        });
    }
}

class List extends Tms {
    api: Api;
    loading: boolean = false
    data: string[] = [];
    constructor(api: Api) {
        super();
        this.api = api;
    }
    $loadStart() {
        this.loading = true;
    }
    $loadDone(response: Response) {
        if (response.code === 0) {
            this.data = response.data;
        }
        this.loading = false;
    }
    async getList() {
        this.$loadStart();
        this.$loadDone(await this.api.getList());
    }
}

const list = new List(new Api());

list.getList();

你应该将this.api.getList()请求回来的完整数据,传入Commit方法中,这样就能追踪到这个请求的结果。在Commit方法中去对请求的结果进行处理。

同理,为了能够对所有的请求结果进行监听,所有的请求结果,都应该存储在实例上,通过Commit更新实例的请求结果。

Module

随着应用程序越来越大,我们需要对程序进行拆分成一个一个小的模块。


class Store extends Tms {
    list: List = new List(new Api());
    count: Count = new Count();
}

const store = new Store();

store.list.getList();

Dep

class Count extends Tms {
    value: number = 0;
    $setValue(value: number) {
        this.value = value;
    }
}

const count = new Count();
const onChange = (event: any) => {
    console.log(event);
    /**
        {
            type: '$setValue', // 触发的方法名称
            payload: 100, // 提交的载荷,如果有多个,则取第一个
            payloads: [ 100 ], // 提交的载荷
            target: Count { value: 100 } // 触发事件的目标源
        }
     */
};
// 订阅状态变化,在每个Commit方法执行完成后执行
count.dep.addSub(onChange);

count.$setValue(100);

// 销毁订阅
count.dep.removeSub(onChange);

Dep对象,提供了订阅实例状态和取消实例状态变化订阅的方法,通过这两个基础的API,你可以根据自己的需求进一步封装。