1
molvqingtai 2023-06-08 21:20:43 +08:00
路由开启了 keep-alive ?
|
2
ivslyyy 2023-06-08 21:22:56 +08:00
加 watch ,改成 v-if
|
3
allzc OP @molvqingtai 没用到路由 全局所有组件处在同一阶层上,每个都用 v-if 来控制
|
5
laoyutang 2023-06-09 09:17:48 +08:00
vue3 本身用 v-if 控制是会触发的,加上 pinia 还真没试过
|
6
DICK23 2023-06-09 09:24:39 +08:00
组件关闭后本身没 destroy 吧
|
7
yetrun 2023-06-14 15:18:04 +08:00
你这问题应该与 pinia 无关,onMounted 只会在组件初始化时运行一次。你可以贴一个简短的代码,表达一下你的意思。
|
8
allzc OP @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; |
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 来表达你的意思就好。 |