手写迷你 Vuex
-
第1步:使用 Store 类管理数据,使用 _state 【存储数据】,使用 _mutations 来存储数据修改的函数
_state 和 _mutations 是 Store 的私有属性 -
第2步:把 _state 变量包裹成【响应式数据–》ref / reactive 】 -
第4步:定义 install 方法, 用于将 store 提供给 Vue 组件使用【通过 provide / inject 做数据共享】 -
第5步:在 Store 类中定义 install 方法,用于 app.use(store) 时执行这个函数 -
第6步:使用单例模式向外暴露唯一 Store 实例对象 -
第7步:向外暴露 useStore 和 createStore
第1步:定义 Store 类,声明 _state 和 _mutations 私有属性
- 需要定义
options、_state、_mutations 的类型
import { reactive, UnwrapRef } from "vue";
interface Options<S> {
state: () => S;
mutations: {
[key: string]: (state: UnwrapRef<S>, payload?: any) => void;
}
}
interface StateType<S> {
data: S
}
type MutationType<S> = {
[k in keyof Options<S>["mutations"]]: (state: UnwrapRef<S>, payload?: any) => void;
};
class Store<S> {
private _state: UnwrapRef<StateType<S>>;
private _mutations: MutationType<S>;
constructor(options: Options<S>) {
this._state = reactive({
data: options.state()
});
this._mutations = options.mutations;
}
}
第2步:定义 state getter 属性方法
...
class Store<S extends object> {
...
get state(): UnwrapRef<S> {
return this._state.data;
}
}
第3步:定义 commit 方法
...
class Store<S extends object> {
...
commit(type: string, payload?: any) {
const entry = this._mutations[type];
entry && entry(this.state, payload);
}
}
第4步:定义 install 方法用于在 Vue 中注册 store
main.ts 入口处 app.use(store) 的时候会执行这个 install 函数
import { App } from "vue";
...
class Store<S> {
static STORE_KEY = '__store__';
...
install(app: App) {
app.provide(Store.STORE_KEY, this);
}
}
第5步:使用单例模式向外暴露唯一的 Store 实例对象
...
class Store<S> {
static STORE_KEY = "__store__";
static instance: Store<any> | null = null;
static getInstance<S>(options: Options<S>): Store<S> {
if (!Store.instance) Store.instance = new Store<S>(options);
return Store.instance;
}
...
}
export function createStore<S extends object>(options: Options<S>) {
return Store.getInstance<S>(options);
}
第6步:向外暴露 useStore 方法
import { inject } from "vue";
...
export function useStore<S extends object>(): Store<S> {
return inject(Store.STORE_KEY)!;
}
第7步:在 store/index.ts 中创建 store
import { createStore } from "./gvuex";
const store = createStore<RootState>({
state() {
return {
count: 666,
};
},
mutations: {
add(state) {
state.count++;
},
},
});
export default store;
第8步:在 main.ts 入口文件中注册 store
main.ts
import { createApp } from "vue";
import App from "./App.vue";
import store from "./store";
createApp(App).use(store).mount("#app");
第9步:在组件中使用 store
<template>
<div @click="add">{{ count }}</div>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { useStore } from "../../store/gvuex2";
const store = useStore<RootState>();
const count = computed(() => store.state.count);
function add() {
store.commit("add");
}
</script>
|