请教下 Vue3 缓存组件删除问题

52 天前
 Artiver

大家好,我最近在学习 Vue3 ,逛 GitHub 看到了一个项目,fork 过来边改边学习,项目地址是:vue3-admin-box,已注明 fork 的原仓库和 License 。

这个后台系统实现了标签页功能,我在组件里的 onBeforeUnmount 方法打了一行 log 用于标识。

onBeforeUnmount(() => {
  console.log('beforeUnmount')
  editor.dispose()
})

但是当前存在一个问题,当我在当前页面点击关闭按钮时,就是下图的 VScode 标签页的 x 按钮,页面关闭后,并不能触发组件的 onBeforeUnmount 方法(图床没法传 gif )。

但是,当我在其他页面,例如主页,点击 VScode 的 x 按钮,就能触发。

不明白这是为什么,有大佬能说下吗?我该如何修正代码,谢谢。

1385 次点击
所在节点    Vue.js
11 条回复
helloWorldzsj
51 天前
从描述看,好像两者的区别是在当前页直接点 x 没有触发 onBeforeUnmount 方法,可以试试其他标签页有无这个问题,如果仍然存在的话,就要看下标签页组件这块的逻辑实现是不是有 bug
freedomT
51 天前
应该是开启了 keepalive 了,用 onDeactivated()
Artiver
51 天前
@freedomT 是的,我的打算是用 keepAlive 缓存一些网页,但是关闭时应该把网页销毁,onDeactivated 的话,在切换标签页时也会触发
jy02534655
51 天前
@Artiver #3 keepAlive 有个缓存名单,打开 tab 页的时候把页面加到缓存名单,点 x 关闭前先把页面从缓存名单中移除再关闭
okrfuse
51 天前
关闭标签页的方法里发送事件总线,要关闭的页面内接收事件总线并执行销毁数据,
shengchao
51 天前
按楼主的描述,点叉的逻辑,改成先路由 push ,再去卸载页面缓存,是不是就可以了
daolanfler
51 天前
感觉像是 vue keep-alive 的 bug ,关闭当前的 tab 之后,虽然 keep-alive 的 include 属性变了,但是页面组件并没有销毁,还存在于内存里面
```js
// 删除菜单项
function delMenu(menu, nextPath) {
let index = 0
index = menuList.value.findIndex((item) => item.path === menu.path)
if (nextPath) {
router.push(nextPath)
return
}
// 若删除的是当前页面,回到前一页,若为最后一页,则回到默认的首页
if (menu.path === activeMenu.path) {
const prePage = index - 1 > 0 ? menuList.value[index - 1] : {path: defaultMenu.path}
router.push({path: prePage.path, query: prePage.query || {}})
}

setTimeout(() => {
if (!menu.meta.hideClose) {
if (menu.meta.cache && menu.name) {
store.commit('keepAlive/delKeepAliveComponentsName', menu.name)
}
menuList.value.splice(index, 1)
}
}, 300);
}
```
如楼上所说,改一下顺序确实可以,但是还必须设置延迟 300ms ,有点莫名其妙。
keep-alive 还是少用,感觉不太靠谱,之前写 vue 的时候,在 dev-tools 经常看同一个页面(组件)的几份缓存,而官方也没有提供清理缓存的 api https://github.com/vuejs/rfcs/pull/284
Artiver
51 天前
@daolanfler 十分感谢,6 楼的意见我昨天试了,也是没成功,没想到需要延时执行,感谢指点!
lovelylain
51 天前
@daolanfler 延迟换成 await nextTick()呢?
daolanfler
50 天前
@lovelylain 也没有,我试过,100ms 也没用,所以我倾向于这是一个 KeepAlive 组件或者 vue-router 的 BUG
Artiver
9 天前
最近在用 pinia 替换 vuex ,发现在 createNode.js 里面实现的刷新网页的回调使用了 setTimeOut ,如下:
```js
timeOut = setTimeout(() => {
nextTick(() => {
NProgress.done();
isReload.value = false;
});
}, 260);
```
修改后貌似解决问题了,感谢各位的抽空解答!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1061014

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX