来自 reactive() 的 Vue3/Vuex 对象一旦在突变中作为有效负载传递给 vuex,就会失去反应性

Posted

技术标签:

【中文标题】来自 reactive() 的 Vue3/Vuex 对象一旦在突变中作为有效负载传递给 vuex,就会失去反应性【英文标题】:Vue3/Vuex Object from reactive() looses reactivity once passed as payload in mutation to vuex 【发布时间】:2021-09-11 16:41:46 【问题描述】:

我知道,或者我不知道,但有些人可能会摸不着头脑,比如“为什么你想要一个可以与提供/注入到你的 Vuex 商店中使用的反应性对象?” ...好吧,因为我可以而且我必须'...

好吧,爸爸开玩笑,我有这个实现身份验证的插件,一旦安装到应用程序中,我会执行“穴居人风格”vuex 插件功能,将其注册到我的 vuex 商店的 namespaced 用户模块中,通过调用突变并传递反应性 const 对象 User,它被包装在 Vue 3 的 reactive 函数中,作为有效负载。现在有趣的是,一旦注册到商店,它就会失去反应性,而提供/注入仍然可以正常工作:)

这里有一些意大利面:

AuthLink.vue

...

export default defineComponent(
    setup() 
        const auth = inject("Auth") as IAuthPluginProperties;

        async function logInFromLink(
            withPopUp = false,
            options?: 
                redirectLoginOptions?: RedirectLoginOptions;
                popupConfigOptions?: PopupConfigOptions;
                analytics: undefined;
            
        ): Promise<void> 
            if (withPopUp) return auth.loginWithPopup();

            //* Potentially add analytics for how many people logged in with the link, from which page etc.

            return await auth.loginWithRedirect(options?.redirectLoginOptions);
        

        function logout(logoutOptions?: LogoutOptions): void 
            auth.logout(logoutOptions);
        

        return 
            auth,
            logInFromLink,
            logout
        ;
    
);
</script>

插件 - index.ts

...
export default 
    install: async (app: App, options: pluginInstallOptions): Promise<void> => 
        app.config.globalProperties.$auth = Plugin.AuthPluginProperties;
        app.provide("Auth", Plugin.AuthPluginProperties);

        /*
         * Could Handle defaulting to.env vars
         *    & then -> if !env vars throw err
         */

        

        if (options.useStore) 
            if (!store.hasModule("User")) 
                throw new Error(
                    "???????????? Something evil is lurking in the shadows...`User` vuex store module has not been registered."
                ).stack;
            

            await vuexPlugin(store, Vue3AuthPlugin.AuthPluginProperties);
       
...

插件 - main.ts

...

const state = reactive(
    isLoading: false,
    isAuthenticated: false,
    user: undefined,
    popupOpen: false,
    error: null
) as IAuthStateProp;

export const AuthPluginProperties = reactive(
    isAuthenticated: computed(() => state.isAuthenticated),
    isLoading: computed(() => state.isLoading),
    user: computed(() => state.user),
    ...some more functions passed here
) as IAuthPluginProperties;

...

store/modules/User/Mutations.ts

import  MutationTree  from "vuex";
import  UserMutations, UserMutationTypes, UserState  from "@/store/types";
import IAuthPluginProperties from "~interfaces/Auth/IAuthPluginProperties";

const mutations: MutationTree<UserState> & UserMutations = 
    [UserMutationTypes.INITIALIZE_PLUGIN](state: UserState, payload: IAuthPluginProperties) 
        state.User = payload;
    
;

export default mutations;

[编辑 1]

忘记添加“穴居人风格”vuex插件功能的代码

auth-vuex-plugin.ts

import  AuthVuexPlugin  from "../types";

const plugin: AuthVuexPlugin<Record<string, unknown>> = async (store, payload) => 
    try 
        await store.dispatch("User/INITIALIZE_PLUGIN", payload);
     catch (err) 
        throw new Error(`???????????? Something evil happened... Vuex init failed: $err`);
    
;

export default plugin;

【问题讨论】:

【参考方案1】:

实际上通过将有效负载传递为ToRefs(payload) 并使用Vue 提供的通用ToRef 键入它(如ToRefs&lt;IAuthState&gt;)来实现我的目标。

我不确定这是否是最好的方法,但会为任何人留下空间,或者我是否设法找到更好的东西:)

【讨论】:

以上是关于来自 reactive() 的 Vue3/Vuex 对象一旦在突变中作为有效负载传递给 vuex,就会失去反应性的主要内容,如果未能解决你的问题,请参考以下文章

全面拥抱Vue3,Vuex4 最新详解教程!

为啥 router.push 不起作用? [Vue 3] [Vuex 4]

Vue 3 + vuex 存储未定义

Vite2+TypeScript4+Vue3+vuex4+vueRouter4+elementPlus如何入手开发新项目

6. Vue 引入vuex store

干货 | Reactive模式优势与实战