V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Artiver
V2EX  ›  Vue.js

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

  •  
  •   Artiver · 101 天前 · 1606 次点击
    这是一个创建于 101 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    pkLN0HJ.png

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

    pkLNc36.png

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

    11 条回复    2024-09-10 23:18:49 +08:00
    helloWorldzsj
        1
    helloWorldzsj  
       100 天前
    从描述看,好像两者的区别是在当前页直接点 x 没有触发 onBeforeUnmount 方法,可以试试其他标签页有无这个问题,如果仍然存在的话,就要看下标签页组件这块的逻辑实现是不是有 bug
    freedomT
        2
    freedomT  
       100 天前
    应该是开启了 keepalive 了,用 onDeactivated()
    Artiver
        3
    Artiver  
    OP
       100 天前
    @freedomT 是的,我的打算是用 keepAlive 缓存一些网页,但是关闭时应该把网页销毁,onDeactivated 的话,在切换标签页时也会触发
    jy02534655
        4
    jy02534655  
       100 天前
    @Artiver #3 keepAlive 有个缓存名单,打开 tab 页的时候把页面加到缓存名单,点 x 关闭前先把页面从缓存名单中移除再关闭
    okrfuse
        5
    okrfuse  
       100 天前
    关闭标签页的方法里发送事件总线,要关闭的页面内接收事件总线并执行销毁数据,
    shengchao
        6
    shengchao  
       100 天前
    按楼主的描述,点叉的逻辑,改成先路由 push ,再去卸载页面缓存,是不是就可以了
    daolanfler
        7
    daolanfler  
       100 天前
    感觉像是 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
        8
    Artiver  
    OP
       100 天前
    @daolanfler 十分感谢,6 楼的意见我昨天试了,也是没成功,没想到需要延时执行,感谢指点!
    lovelylain
        9
    lovelylain  
       100 天前 via Android
    @daolanfler 延迟换成 await nextTick()呢?
    daolanfler
        10
    daolanfler  
       99 天前
    @lovelylain 也没有,我试过,100ms 也没用,所以我倾向于这是一个 KeepAlive 组件或者 vue-router 的 BUG
    Artiver
        11
    Artiver  
    OP
       58 天前
    最近在用 pinia 替换 vuex ,发现在 createNode.js 里面实现的刷新网页的回调使用了 setTimeOut ,如下:
    ```js
    timeOut = setTimeout(() => {
    nextTick(() => {
    NProgress.done();
    isReload.value = false;
    });
    }, 260);
    ```
    修改后貌似解决问题了,感谢各位的抽空解答!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1765 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 16:39 · PVG 00:39 · LAX 08:39 · JFK 11:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.