通过 pinia 集中控制 vue 组件的显隐,不二次触发 onMounted - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
allzc
V2EX    Vue.js

通过 pinia 集中控制 vue 组件的显隐,不二次触发 onMounted

  •  
  •   allzc 2023-06-08 21:15:36 +08:00 2195 次点击
    这是一个创建于 917 天前的主题,其中的信息可能已经有所发展或是发生改变。
    vue3 通过 pinia 集中处理每个组件的状态(尝试写,因为大屏组件太多了,层层套进),初次开启每个组件都是 ok 的,会触发 onMounted ,但是二次关闭再打开后,onMounted 没有触发,这是因为啥,目前通过 store.$onAction 这个监听状态,来插写 onMounted 里面的具体内容
    11 条回复    2023-09-26 23:28:34 +08:00
    molvqingtai
        1
    molvqingtai  
       2023-06-08 21:20:43 +08:00
    路由开启了 keep-alive ?
    ivslyyy
        2
    ivslyyy  
       2023-06-08 21:22:56 +08:00
    加 watch ,改成 v-if
    allzc
        3
    allzc  
    OP
       2023-06-08 21:25:51 +08:00
    @molvqingtai 没用到路由 全局所有组件处在同一阶层上,每个都用 v-if 来控制
    allzc
        4
    allzc  
    OP
       2023-06-08 21:26:56 +08:00
    @ivslyyy 用的就是 v-if watch 具体监听什么?监听这个 store 嘛
    laoyutang
        5
    laoyutang  
       2023-06-09 09:17:48 +08:00
    vue3 本身用 v-if 控制是会触发的,加上 pinia 还真没试过
    DICK23
        6
    DICK23  
       2023-06-09 09:24:39 +08:00
    组件关闭后本身没 destroy 吧
    yetrun
        7
    yetrun  
       2023-06-14 15:18:04 +08:00
    你这问题应该与 pinia 无关,onMounted 只会在组初始化时运行一次。你可以贴一个简短的代码,表达一下你的意思。
    allzc
        8
    allzc  
    OP
       2023-06-19 15:45:55 +08:00
    @yetrun

    我的逻辑是动态引入一个文件夹下的所有组件,给与一个状态 compState ,然后通过外部调用改变 store 中这个组件的状态,来控制显隐,比如下面的组件 B 通过 singleComp 控制 A 显示

    现在的情况是 我在框架刚开始搭建的时候 onUpdated 会执行以及之后的方法 onBeforeUnmount 等等 onMounted 不执行 组件变多后变成只执行 onMounted 并且关闭再打开 不会再执行 onMounted

    不明所以,所以我现在直接放在$onAction 去处理,不再用 vue 的声明周期去控制

    具体看代码吧
    -------------------------------------------------组件 A-----------------------------------------------------------------------
    <template>
    <div v-if="compInfo.compState">......</div>
    </template>

    <script>
    import useWatchComp from "@/hooks/useWatchComp.js";

    export default {
    name: "AAAAAAAA",
    setup() {
    const { compInfo } = useWatchComp(onMountedFunc, compInfoChange);
    function onMountedFunc() {
    要初始化的方法。。。。。。
    }
    function compInfoChange(newInfo) {
    状态改变触发的方法
    }
    return { compInfo};
    },
    };


    -------------------------------------------------组件 B-----------------------------------------------------------------------
    <template>
    <div v-if="compInfo.compState">
    <btn @click="showAAAAAAAA" />
    </div>
    </template>

    <script>
    import useWatchComp from "@/hooks/useWatchComp.js";
    import useComp from "@/hooks/useComp.js";

    export default {
    name: "BBBBBBBB",
    setup() {
    const { compInfo } = useWatchComp(onMountedFunc, compInfoChange);
    const { singleComp } = useComp();

    function onMountedFunc() {
    要初始化的方法。。。。。。
    }
    function compInfoChange(newInfo) {
    状态改变触发的方法
    }

    function showAAAAAAAA() {
    singleComp({
    compName: "AAAAAAAA",
    compState: true,
    compParams: { data: item },
    });
    }
    return {
    compInfo,showAAAAAAAA
    };
    },
    };
    </script>


    -------------------------------------------------useWatchComp.js-----------------------------------------------------------------------

    import { computed, getCurrentInstance } from "vue";
    import compControl from "@/store/compControl.js";

    const useWatchComp = (onMountedFunc, compInfoChange) => {
    const instance = getCurrentInstance();
    let compStore = compControl();
    let compName = instance.type.name;
    let compInfo = computed(() => {
    return compStore[compName];
    });


    //我的本意是将传入的 onMountedFunc 方法放入对应的 onMounted 执行 每次组件打开的话对应执行,但有一开始讲述的问题

    onBeforeMount(()=>{})
    onMounted(()=>{
    onMountedFunc()
    })
    onBeforeUpdate(()=>{})
    onUpdated(()=>{})
    onBeforeUnmount(()=>{})
    onUnmounted(()=>{})





    // 组件信息变动
    compStore.$onAction(
    ({
    name, store, args,after,onError,
    }) => {
    after(() => {
    //所以我全部放在这里面去执行
    onMountedFunc()
    });
    onError((error) => {});
    }
    );

    return {
    compInfo,
    };
    };
    export default useWatchComp;

    -------------------------------------------------useComp.js-----------------------------------------------------------------------

    import compControl from "@/store/compControl.js";

    const useComp = () => {
    let compStore = compControl();
    // 触发单个组件
    const singleComp = ({ compName, compState, compParams = {} }) => {
    compStore.singleCompControl({
    compName,
    compState,
    compParams,
    });
    };
    // 触发多个组件
    const batchComp = ({ compList, beforeClear = false }) => {
    compStore.batchCompControl({
    beforeClear,
    compList,
    });
    };

    return {
    singleComp,
    batchComp,
    };
    };
    export default useComp;



    -------------------------------------------------store/compControl.js----------------------------------------------------------------------
    import { defineStore } from "pinia";
    import { forIn } from "lodash";
    let files = import.meta.globEager("@/views/components/*.vue");
    let state = {};
    forIn(files, (value, key) => {
    let compName = key.replace(/\/src\/views\/components\/|\.vue/g, "");
    state[compName] = {
    compName,
    compState: false,
    compParams: {},
    };
    });

    const useCompStore = defineStore("compControl", {
    state: () => {
    return state;
    },
    actions: {
    // 批量
    batchCompControl({ beforeClear = false, compList }) {
    if (beforeClear) {
    forIn(state, (value, key) => {
    this[key].compState = false;
    this[key].compParams = {};
    });
    }
    compList.forEach(({ compName, compState, compParams = {} }) => {
    this[compName].compState = compState;
    this[compName].compParams = compParams;
    });
    },
    // 单个
    singleCompControl({ compName, compState, compParams = {} }) {
    this[compName].compState = compState;
    this[compName].compParams = compParams;
    },
    },
    });

    export default useCompStore;
    allzc
        9
    allzc  
    OP
       2023-06-19 15:47:11 +08:00
    @DICK23 destroy 不执行了 感觉这种控制方式影响了整个生命周期的问题了 具体可以看下 下面的代码回复
    yetrun
        10
    yetrun  
       2023-07-03 12:20:16 +08:00
    @allzc 对不起,今天才看到。你的代码不够简短啊,而且排版还不够好,这不好看懂。如果你确实遇到问题了,建议你将代码精简到只复现问题的部分,保证代码足够简短方便讨论。如果确实要上传这么复杂的代码,建议你将出问题的代码打包成一个项目上传到 stackblitz 或 Github 这样的地方,并保证能够复现,方便我们直接拉取项目针对性地解决问题。

    ---分折线---

    我还是稍微看了下代码,尝试性地给你个答复吧。我看到你的组件 A 的代码,我暂且理解为这是你控制显隐的其中一个组件。我看到你将 v-if 放在组件内部的一个 div 了:

    <div v-if="compInfo.compState">......</div>

    这样是不会触发组件 A 的 onMounted 方法的。

    另一个方面,你的 useWatchComp 方法作为你用到的一个公共钩子函数,我尝试的理解是,你在这里面想自己去做一套回调的逻辑,在组件初次加载和组件信息变动时,去执行你传进来的 onMountedFunc 函数。但由于是你自己管理的逻辑,与 Vue 组件生命周期无关了。所以你的问题不应该是“用 pinia 导致不二次触发 onMounted”,而应该是“你想通过 pinia 集中控制 Vue 组件的显隐,并在组件每次执行时执行一个 onMountedFunc 函数,但从第二次显示开始这个函数都不执行了"。

    我对 pinia 不熟,再加上代码排版看上去不好,导致我现在没法就这个问题给你解答。应该是某处出现了一个隐藏的 Bug 导致你的问题出现。但如果是我理解的那个样子,那这个问题应该是限制在 pinia 的专业问题,与 Vue 本身应该没有关系了。

    ---分折线---

    最后我总结一下,onMounted 是 Vue 组件生命周期的一部份,在一个组件实例加载过程中只会执行一次。Pinia 的加入不会改变这个基本的逻辑。

    你的问题是想用 pinia 管理一下自己的逻辑,比如每次组件显示的时候执行一个自定义的加载函数 onMountedFunc. 那如果是这样,就不要用 onMounted 来指代了,因为它是 Vue 生命周期的一个回调函数,很容易引起歧义。用 onMountedFunc 来表达你的意思就好。
    allzc
        11
    allzc  
    OP
       2023-09-26 23:28:34 +08:00 via iPhone
    @yetrun 谢谢大佬回答,有心了,一直忘了登,不好意思,你说的方向是对的,我现在解决了,彻底不用生命周期去控制每个组件了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2855 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 00:21 PVG 08:21 LAX 16:21 JFK 19:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86