手写 —— mini-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;
};
// 泛型参数 S 用于约束 state 的类型
class Store<S> {
// _state 是一个响应式数据,
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__'; // 用作 project/inject 的属性名
...
install(app: App) {
// 向所有组件提供 __store__ 属性,值为 Store 实例对象
app.provide(Store.STORE_KEY, this);
}
}
第5步:使用单例模式向外暴露唯一的 Store 实例对象
...
class Store<S> {
static STORE_KEY = "__store__"; // 用作 project/inject 的属性名
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;
}
...
}
// 向外暴露唯一个 Store 对象
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>
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!