3
votes

I have a fairly large vue.js 2 application that has a dynamic tabs mechanism. Users can interact with the application opening and closing tabs, each tab represents a route. To achieve this I'm using vue router and keep alive, like the example bellow.

<template>
  <div id="app">
    <keep-alive>
      <router-view :key="routerViewKey"/>
    </keep-alive>
  </div>
</template>

When users click the close tab button, the $destroy function is called to remove its component from the cache. I'm migrating this application from vue 2 to vue 3, however, reading the breaking changes documentation for vue.js 3 we can see this:

Removed APIs

$destroy instance method. Users should no longer manually manage the lifecycle of individual Vue components.

I didn't find any alternatives so far, so how can I programmatically destroy/unmount a cached component inside keep-alive in vue.js 3?

2

2 Answers

3
votes

You can find the unmount command here: https://v3.vuejs.org/api/application-api.html#unmount

Unfortunately, if you want to do it inside your app, the documentation doesn't have any way to do it. However, after analyzing the object, I found a way to do it. You can achieve it by using this: this.$.appContext.app.unmount();

I'm not a huge fan of this solution, given that it can no longer work in a future version, but it works well on my project.

EDIT: Another way is to extend the Vue object according to this: https://github.com/vuejs/vue-next/issues/1802 and https://github.com/pearofducks/mount-vue-component

I have slightly improved the function:

function mount(component, { props, children, element, app } = {}) {
    let el = element
  
    let vNode = createVNode(component, props, children)
    vNode.destroy = () => {
        if (el) render(null, el)
        el = null
        vNode = null
    }
    if (app?._context) vNode.appContext = app._context
    if (el) render(vNode, el)
    else if (typeof document !== 'undefined' ) render(vNode, el = document.createElement('div'))
  
    const destroy = () => {
        if (el) render(null, el)
        el = null
        vNode = null
    }
  
    return { vNode, destroy, el }
}

You can now track which component you have as children, destroy it from the parent AND the children by using this: this.$.vnode.destroy();

However, the new official way seems to use createApp now.

2
votes

The destroy hook has been replaced with unmounted. I guess you can import unmounted from the composition APIs.