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

问题描述

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

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

这里有一些意大利面:

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;

...

存储/模块/用户/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;

标签: typescriptvue.jsvuexvuejs3vue-reactivity

解决方案


ToRefs(payload)实际上通过传递有效负载以及使用 Vue 提供的通用 ToRef 键入它来实现我所追求的,例如ToRefs<IAuthState>.

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


推荐阅读