• Vue3全局共享数据


    1,Vuex

    vue2 的官方状态管理器,vue3 也是可以用的,需要使用 4.x 版本

    相对于 vuex3.x,有两个重要变动:

    • 去掉构造函数 Vuex,而使用 createStore() 创建仓库
    • 为了配合 compositionAPI,新增 useStore() 获取仓库对象

    先看一个使用 vuex 的例子:实现登录、刷新页面恢复登录、退出登录的状态管理。

    // store/index.js
    import loginUser from "./loginUser";
    import { createStore, createLogger } from "vuex";
    export default createStore({
      modules: {
        loginUser,
      },
      plugins: [createLogger()], // 用于调试,会在控制台打印日志。
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    createLogger 官网参考

    // store/loginUser.js
    export default {
      namespaced: true,
      state: {
        user: null,
        loading: false,
      },
      mutations: {
        setUser(state, payload) {
          state.user = payload;
        },
        setLoading(state, payload) {
          state.loading = payload;
        },
      },
      actions: {
        async login({ commit }, { loginId, loginPwd }) {
          commit("setLoading", true);
          // 登录接口
          const user = await _faker.login(loginId, loginPwd);
          commit("setUser", user);
          commit("setLoading", false);
          return user;
        },
        async loginOut({ commit }) {
          commit("setLoading", true);
          // 退出登录接口
          await _faker.loginOut();
          commit("setUser", null);
          commit("setLoading", false);
        },
        async whoAmI({ commit }) {
          commit("setLoading", true);
          // 恢复登录接口
          const user = await _faker.whoAmI();
          commit("setUser", user);
          commit("setLoading", false);
        },
      },
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    组件中使用 store

    <script setup>
    import { computed, ref } from "vue";
    import { useStore } from "vuex";
    
    const store = useStore();
    
    const loginId = ref("");
    const loginPwd = ref("");
    const loading = computed(() => store.state.loginUser.loading),
    
    const handleSubmit = async () => {
      const user = await store.dispatch("loginUser/login", {
        loginId: loginId.value,
        loginPwd: loginPwd.value,
      });
      if (user) {
         // 登录成功,跳转首页。
      } else {
        alert("账号/密码错误");
      }
    };
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注册

    // main.js
    import { createApp } from "vue";
    import App from "./App.vue";
    import store from "./store";
    createApp(App).use(store).mount("#app");
    
    // 恢复登录,其实就是把存在本地的用户信息,再次放到 store 中。
    store.dispatch("loginUser/whoAmI");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2,provide & inject

    vue2 中就有这2个配置,可以在祖先组件中注入数据,然后在后代组件中使用。

    vue3 的 optionAPI 做了兼容的同时,compositionAPI 也提供了 provide()inject()-官网-依赖注入

    另外,考虑到部分数据会在整个 vue 应用中使用,所以 vue3 在应用实例中也添加了 provide(), 用于提供整个应用的共享数据

    import { createApp } from "vue";
    import App from "./App.vue";
    creaetApp(App)
      .provide("foo", ref(1))
      .provide("bar", ref(2))
      .mount("#app");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    来模仿 vuex 的使用方式来实现上面的例子。

    // store/index.js
    import { provideStore as provideLoginUserStore } from "./useLoginUser";
    // 继续导入其他共享数据模块...
    // import { provideStore as provideNewsStore } from "./useNews"
    
    // 提供统一的数据注入接口
    export default function provideStore(app) {
      provideLoginUserStore(app);
      // 继续注入其他共享数据
      // provideNewsStore(app);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    // store/userLoginUser.js
    import { readonly, reactive, inject } from "vue";
    const key = Symbol(); // Provide的key
    
    // 在传入的vue应用实例中提供数据
    export function provideStore(app) {
      // 创建默认的响应式数据
      const state = reactive({ user: null, loading: false });
      // 登录
      async function login(loginId, loginPwd) {
        state.loading = true;
        const user = await _faker.login(loginId, loginPwd);
        state.user = user;
        state.loading = false;
      }
      // 退出
      async function loginOut() {
        state.loading = true;
        await _faker.loginOut();
        state.loading = false;
        state.user = null;
      }
      // 恢复登录状态
      async function whoAmI() {
        state.loading = true;
        const user = await _faker.whoAmI();
        state.loading = false;
        state.user = user;
      }
      // 提供全局数据
      app.provide(key, {
        state: readonly(state), // 对外只读
        login,
        loginOut,
        whoAmI,
      });
    }
    
    export function useStore(defaultValue = null) {
      return inject(key, defaultValue);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    组件中使用 store

    <script setup>
    import { computed, ref } from "vue";
    import { useStore } from "../store/useLoginUser";
    
    const store = useStore();
    
    const loginId = ref("");
    const loginPwd = ref("");
    const loading = computed(() => store.state.loading),
    
    const handleSubmit = async () => {
      const user = await store.login(loginId.value, loginPwd.value);
      if (store.state.user) {
         // 登录成功,跳转首页。
      } else {
        alert("账号/密码错误");
      }
    };
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    全局注册

    // main.js
    import { createApp } from "vue";
    import App from "./App.vue";
    import provideStore from "./store";
    const app = createApp(App);
    provideStore(app); // 上面的封装形式,即便项目中存在多个应用实例,也可以应对。
    app.mount("#app");
    
    // 恢复登录,要放到 App.vue 中执行了。
    // whoAmI();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2,global state

    得益于 vue3 的响应式系统是可以脱离组件而存在,所以可轻松创建多个全局响应式数据。

    // store/useLoginUser.js
    import { reactive, readonly } from "vue";
    
    // 创建默认的全局单例响应式数据,仅供该模块内部使用
    const state = reactive({ user: null, loading: false });
    
    // 对外暴露的数据是只读的,不能直接修改
    export const loginUserStore = readonly(state);
    
    // 登录
    export async function login(loginId, loginPwd) {
      state.loading = true;
      const user = await _faker.login(loginId, loginPwd);
      state.user = user;
      state.loading = false;
    }
    // 退出
    export async function loginOut() {
      state.loading = true;
      await _faker.loginOut();
      state.loading = false;
      state.user = null;
    }
    // 恢复登录状态
    export async function whoAmI() {
      state.loading = true;
      const user = await _faker.whoAmI();
      state.loading = false;
      state.user = user;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    组件中使用 store

    <script setup>
    import { computed, ref } from "vue";
    import { loginUserStore, login } from "../store/useLoginUser";
    
    const loginId = ref("");
    const loginPwd = ref("");
    // 模版也可以直接使用 loginUserStore.loading
    const loading = computed(() => loginUserStore.loading),
    
    const handleSubmit = async () => {
      const user = await login(loginId.value, loginPwd.value);
      if (user) {
         // 登录成功,跳转首页。
      } else {
        alert("账号/密码错误");
      }
    };
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    全局注册

    // main.js
    import { createApp } from "vue";
    import App from "./App.vue";
    import { whoAmI } from "./store/useLoginUser";
    createApp(App).mount("#app");
    
    // 恢复登录
    whoAmI();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4,Pinia

    官网参考

    5,对比

    vuexglobal stateProvide&Inject
    组件数据共享
    可否脱离组件
    量级

    以上。

  • 相关阅读:
    基于SSM的网络安全宣传网站设计与实现
    X Spring File Storage实现文件上传与下载
    go RWMutex 的实现
    JAVA桌游店会员管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
    visual studio 2022一个不易发现的问题(难找且诡异)
    新加坡反诈骗中心与六家银行联手,利用RPA技术成功避免1710万美元损失
    【沐风老师】3DMAX路径拖尾光线刀光效果插件GhostTrails教程
    leetcode 1562. 查找大小为 M 的最新分组
    基于JAVA疫情下的居民管理系统计算机毕业设计源码+系统+数据库+lw文档+部署
    第二章 JAVA基础语法
  • 原文地址:https://blog.csdn.net/qq_40147756/article/details/134301481