美文网首页
高效的在Vue3中使用Vuex

高效的在Vue3中使用Vuex

作者: 乌云龙 | 来源:发表于2021-06-22 11:52 被阅读0次

    前言

    我们都知道,vuex 的使用在项目中颇为繁琐,因为它有几大概念使得它不能像普通 ref 或者 data 对象一样直接被我们使用,在我们想要更改 vuex 中的数据时,我们需要通过 mutation 来进行提交,获取 vuex 中存储的变量的时候,我们又需要通过 computed 属性来进行声明,试想,如果项目足够庞大,那么我们使用 vuex 的负担就过于重了,这违背了我们使用状态管理的本意。

    问题的提出

    首先,我们需要明确,我们想要怎么快捷便利地来使用 vuex ,如果你的想法和我如下所示相同,那么恭喜你,或许本文提出的解决方案适合你。

    存储

    对于 vuex 的存储我们想要实现的类似如下:

    this.$m.vuex(name,value);
    

    我们可以在各个组件或者视图内,通过 this 来直接使用 vuex 进行存储。

    读取

    对于 vuex 中数据的读取我们想要实现的类似如下:

    <template>
    <div>{{ vuexUser.name }}</div>
    </template>
    
    
    <script lang="ts">
    import { defineComponent } from 'vue'
    export default defineComponent({
        ...
        methods:{
              // 业务方法
              xxxxx(){
                const flag = this.vuexUser.name? true : false;
                .....
              }
      }
    })
    </script>
    

    我们能够在模板或者业务逻辑中直接通过 this 直接访问。

    解决方案

    首先,我们需要在 store 目录下的 index.ts 内加入如下代码

    import { createStore } from 'vuex'
    
    export default createStore({
      state: {
        vuexIsLogin: false,        // 当前的登录状态
        vuexTestVar: "测试变量",
        vuexUser:{
          test: 1,
          name: "WuYunLong"
        }
      },
      mutations: {
        $changeStore(state: any, payload: any){
          // 判断是否为多层级调用
          const nameArr = payload.name.split('.');
          const len = nameArr.length;
          if ( len >= 2){
    
            let obj = state[nameArr[0]];
            for (let i = 1 ; i < len - 1 ; i++){
              obj = obj[nameArr[i]];
            }
            obj[nameArr[len-1]] = payload.value;
          }else {
            state[payload.name] = payload.value;
          }
        }
      }
    })
    

    之后我们在 store 目录下创建一个 ts 脚本文件,在我的项目中我命名为 maxer.mixin.ts ,在这里,我们就需要使用 Vue 中的一个特性 Mixin(混入)「不明白的同学可以去官方文档查一查,Vue3 的官方中文版已经推出了」

    /**
     * @作者: WuYunlong
     * @时间: 2021/06/22
     * @版本: V1.0
     * @说明: maxer Vue 全局混入
     */
    
    import { App } from 'vue'
    import { mapState } from "vuex";
    import store from '@/store/index.ts'
    
    // 将定义的state变量key全部加载到全局变量中
    const $mStoreKey = store.state ? Object.keys(store.state) : [];
    export class Maxer{
        vuex = (name: string, value: any): void=>{
            store.commit('$changeStore', {
                name, value
            })
        }
    }
    
    export default<T> (app: App<T>) => {
        // 进行全局混入
        // 将vuex方法挂载到$m中
        // 使用方法为: this.$m.vuex('user.name', 'x')
        app.config.globalProperties.$m = new Maxer();
        app.mixin({
            computed: {
                // 将vuex的state中的所有变量,解构到全局混入的mixin中
                ...mapState($mStoreKey)
            }
        })
    }
    

    在这里我们使用全局混入,将 vuex 的 state 混入到计算属性中,我们就可以通过类似 this.vuexName 来进行调用,还有一点建议就是,由于采用全局混入的模式将 vuex 中的数据进行混入,所以我们应该用特定的字符来进行标识 vuex 中的数据,我的建议是在 vuex 中变量前加上特殊前缀 ,或者类似 vuexVar:'xxx' 来进行声明变量。

    之后我们就需要在 main.ts 中进行初始化了。

    import { createApp } from 'vue'
    import App from './App.vue'
    import store from './store'
    import installMaxerStore, { Maxer } from './store/maxer.mixin'
    ...
    
    // 声明全局组件 防止需要this调用时不能识别类型
    declare module '@vue/runtime-core' {
        interface ComponentCustomProperties {
            $m: Maxer;  // 声明全局方法
        }
    }
    ...
    const app = createApp(App)
    installMaxerStore(app)
    app.use(store).mount('#app')
    

    之后我们就可以愉快地使用 vuex 了(在注意变量命名的情况下)。

    Vuex 数据持久化

    这个时候或许你会发现,当页面进行刷新的时候,vuex 的数据会进行初始化(回到最初的状态),这个是由于 vuex 是运行在内存中的,同样的,它的数据也是存储在内存中,当用户进行刷新页面的操作,所以内存数据会重新进行初始化。

    那么我们就可以通过 sessionStorage /localStorage/cookie 来进行数据的持久化存储。

    页面加载的时候先读取域中的缓存数据,如果有则覆写。当页面将要刷新前,我们将 vuex 的数据存储到域中。

    这里建议使用 sessionStorage ,对于需要长时间持久化的数据再使用 localStorage 或者 cookie。

    同样我们在 store 目录下新建一个 ts 脚本。

    /**
     * @作者: WuYunlong
     * @时间: 2021/6/22
     * @版本: V1.0
     * @说明: vuex数据持久化,防止F5之后数据消失
     */
    import {Store} from "vuex";
    
    export default<T> (store: Store<T>): void=>{
        // 不需要持久化的数据存入sessionStorage
        if (sessionStorage.getItem('store')){
            store.replaceState(
                Object.assign(
                    {},
                    store.state,
                    JSON.parse(sessionStorage.getItem('store') as string)
                )
            );
            // 移除sessionStorage中的数据
            sessionStorage.removeItem("store");
        }
        // 页面刷新的时候进行持久化
        window.addEventListener('beforeunload',()=>{
            sessionStorage.setItem("store", JSON.stringify(store.state));
        })
    }
    

    对于需要长时间持久化的数据建议自行定义规则进行封装。

    之后我们需要在入口文件中进行声明

    import { createApp } from 'vue'
    import App from './App.vue'
    import store from './store'
    import installMaxerStore, {Maxer} from './store/maxer.mixin'
    import initStorePersistence from './store/store.persistence'
    ...
    
    // 声明全局组件
    declare module '@vue/runtime-core' {
        interface ComponentCustomProperties {
            $m: Maxer;  // 声明全局方法
        }
    }
    ...
    const app = createApp(App)
    installMaxerStore(app) // 全局混入vuex
    initStorePersistence(store) // 初始化持久化vuex
    app.use(store).mount('#app')
    

    版权说明

    本文章转载自网络,如果侵犯了您的权利起联系删除。

    相关文章

      网友评论

          本文标题:高效的在Vue3中使用Vuex

          本文链接:https://www.haomeiwen.com/subject/cpwpyltx.html