Vue-router: Remove all beforeEach, afterEach, beforeResolve

Created on 6 Aug 2018  路  3Comments  路  Source: vuejs/vue-router

Version

3.0.1

Reproduction link

https://jsfiddle.net/se6gLaqn/1/

Steps to reproduce

Create a vue instance, as well as a router instance. Then destroy the vue instance.

The router instance continues to exist and fire.

What is expected?

The router should be able to properly destroy itself; either by explicit call, or when the vue instance is destroyed

What is actually happening?

The router exists and cannot be destroyed


I did some googling and see that vue-router cannot currently be destroyed, but I am asking for reconsideration. Unlike the other issue I found (https://github.com/vuejs/vue-router/issues/954) where it appeared the user wanted to destroy and create a new router in the same application, the issue I am having is completely separate.

I have a massive application that essentially uses pjax methodologies to be able to run several SPAs (vue being one) that create the full site. When we navigate away from one SPA to another, the SPA needs to destroy itself so it's code does not interfere with the other SPAs. However, because the vue router cannot be destroyed; it's attempting to execute logic for routing even when the SPA that created it is destroyed. The issue compounds when we have more than 1 vue application running, as there are now 2 instances of vue-router (or more) running at a time.

Specifically, we are using the hash version of routing. It looks like the router just attaches an event to the window and listens for popstates, but things get weird when more than one event does something with popstate (an understandably oddball behavior). I would appreciate reconsideration for allowing vue-router to destroy itself when appropriate. Thanks!

[edited for spelling/grammar]

feature request micro frontends

Most helpful comment

I'm also interested in this functionality. Looking at #1102, I see that a single router can be injected into multiple Vue instances: router.apps is the array of those instances. I wonder if something like the following would be possible:

  • When a Vue instance is destroyed, it asks the router to remove it from router.apps.
  • If router.apps becomes empty:

    • router.app becomes null.

    • The router asks its history instance to remove its listeners.

  • If the router is then injected into a new Vue instance:

    • router.app is set to that instance.

    • The router asks its history instance to set up listeners again.

If something like that were in place, I think it'd be possible for multiple routers to coexist as long as only one of them at a time has been injected into a non-destroyed Vue instance.

All 3 comments

I'm also interested in this functionality. Looking at #1102, I see that a single router can be injected into multiple Vue instances: router.apps is the array of those instances. I wonder if something like the following would be possible:

  • When a Vue instance is destroyed, it asks the router to remove it from router.apps.
  • If router.apps becomes empty:

    • router.app becomes null.

    • The router asks its history instance to remove its listeners.

  • If the router is then injected into a new Vue instance:

    • router.app is set to that instance.

    • The router asks its history instance to set up listeners again.

If something like that were in place, I think it'd be possible for multiple routers to coexist as long as only one of them at a time has been injected into a non-destroyed Vue instance.

After looking at other issues like https://github.com/vuejs/vue-router/issues/2639, we cannot just remove all listeners from the router. We can however unset router.app.

Currently, you have to keep the returned value from beforeEach, which is a function you can call to unsubscribe later:

const stop = router.beforeEach((to, from, next) => {
  let rte =  document.getElementById('someMessage')
console.log(to)
  rte.innerText = `Router Path: ${to.path}`
  next()
})

let vm = new Vue({
    router,
  el: '#app',
  data: {
    msg: 'Hello World'
  }
})

setTimeout(() => {
  console.log("about to destroy")
let dest =  document.getElementById('destroyed')
    dest.innerText = `vm.destroy() called, vue is dead. but the router still works. booo`
  vm.$destroy()
  stop()
}, 10000)

I'm changing this into a feature request to remove all listeners

I have put together a fix for this at https://github.com/vuejs/vue-router/pull/3172

Was this page helpful?
0 / 5 - 0 ratings