最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue手写系列 —— mini-vuex - 掘金

    正文概述 掘金(爱笑的小皮卡)   2021-11-20   968

    手写 —— mini-vuex

    • 第1步:使用 Store 类管理数据,使用 _state 【存储数据】,使用 _mutations 来存储数据修改的函数

      • _state_mutationsStore 的私有属性
    • 第2步:把 _state 变量包裹成【响应式数据--》ref / reactive
    • 第4步:定义 install 方法, 用于将 store 提供给 Vue 组件使用【通过 provide / inject 做数据共享】
    • 第5步:在 Store 类中定义 install 方法,用于 app.use(store) 时执行这个函数
    • 第6步:使用单例模式向外暴露唯一 Store 实例对象
    • 第7步:向外暴露 useStorecreateStore

    vue手写系列 —— mini-vuex - 掘金

    第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>
    

    vue手写系列 —— mini-vuex - 掘金


    起源地下载网 » vue手写系列 —— mini-vuex - 掘金

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元