diff --git a/examples/index.html b/examples/index.html index f9fbf1b9a..5f2cd4f32 100644 --- a/examples/index.html +++ b/examples/index.html @@ -29,6 +29,7 @@

Vue Router Examples

  • Nested Routers
  • Keepalive View
  • Multiple Apps
  • +
  • Restart App
  • diff --git a/examples/restart-app/app.js b/examples/restart-app/app.js new file mode 100644 index 000000000..424affe10 --- /dev/null +++ b/examples/restart-app/app.js @@ -0,0 +1,66 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' + +const Home = { template: '
    home
    ' } +const Foo = { template: '
    foo
    ' } + +const routes = [ + { path: '/', component: Home }, + { path: '/foo', component: Foo } +] + +const router = new VueRouter({ + mode: 'history', + base: __dirname, + routes +}) + +// track number of beforeResolve +const increment = name => { + const counter = document.getElementById(name) + counter.innerHTML++ +} + +document.getElementById('beforeEach').innerHTML = 0 +router.beforeEach((to, from, next) => { + increment('beforeEach') + next() +}) + +document.getElementById('beforeResolve').innerHTML = 0 +router.beforeResolve((to, from, next) => { + increment('beforeResolve') + next() +}) + +document.getElementById('afterEach').innerHTML = 0 +router.afterEach((to, from) => { + increment('afterEach') +}) + +Vue.use(VueRouter) + +let vueInstance +const mountEl = document.getElementById('mount') +const unmountEl = document.getElementById('unmount') + +mountEl.addEventListener('click', () => { + vueInstance = new Vue({ + router, + template: ` +
    +

    Hello "Restart-app"

    + + +
    + ` + }).$mount('#app') +}) + +unmountEl.addEventListener('click', () => { + vueInstance.$destroy() + vueInstance.$el.innerHTML = '' +}) diff --git a/examples/restart-app/index.html b/examples/restart-app/index.html new file mode 100644 index 000000000..c8885ad66 --- /dev/null +++ b/examples/restart-app/index.html @@ -0,0 +1,21 @@ + + +← Examples index + +
    + + + + +
    + +Count beforeEach:
    +Count beforeResolve:
    +Count afterEach:
    + +
    + +
    + + + \ No newline at end of file diff --git a/src/history/base.js b/src/history/base.js index 072cfb8e8..3397e8709 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -252,11 +252,18 @@ export class History { // Default implementation is empty } - teardownListeners () { + teardown () { + // clean up event listeners + // https://github.com/vuejs/vue-router/issues/2341 this.listeners.forEach(cleanupListener => { cleanupListener() }) this.listeners = [] + + // reset current history route + // https://github.com/vuejs/vue-router/issues/3294 + this.current = START + this.pending = null } } diff --git a/src/index.js b/src/index.js index 22ecff96d..3eda7f778 100644 --- a/src/index.js +++ b/src/index.js @@ -102,11 +102,7 @@ export default class VueRouter { // we do not release the router so it can be reused if (this.app === app) this.app = this.apps[0] || null - if (!this.app) { - // clean up event listeners - // https://github.com/vuejs/vue-router/issues/2341 - this.history.teardownListeners() - } + if (!this.app) this.history.teardown() }) // main app previously initialized diff --git a/test/e2e/specs/restart-app.js b/test/e2e/specs/restart-app.js new file mode 100644 index 000000000..0dca5c3b8 --- /dev/null +++ b/test/e2e/specs/restart-app.js @@ -0,0 +1,45 @@ +const bsStatus = require('../browserstack-send-status') + +module.exports = { + ...bsStatus(), + + '@tags': ['history'], + + basic: function (browser) { + browser + .url('http://localhost:8080/restart-app/') + .waitForElementVisible('#mount', 1000) + .assert.containsText('#beforeEach', '0') + .assert.containsText('#beforeResolve', '0') + .assert.containsText('#afterEach', '0') + + // Mounting will trigger hooks + .click('#mount') + .waitForElementVisible('#app > *', 1000) + .assert.containsText('#beforeEach', '1') + .assert.containsText('#beforeResolve', '1') + .assert.containsText('#afterEach', '1') + .assert.containsText('#view', 'home') + + // Navigate to foo route will trigger hooks + .click('#app li:nth-child(2) a') + .assert.containsText('#beforeEach', '2') + .assert.containsText('#beforeResolve', '2') + .assert.containsText('#afterEach', '2') + .assert.containsText('#view', 'foo') + + // Unmount + .click('#unmount') + .assert.containsText('#app', '') + + // Second mounting will trigger hooks + .click('#mount') + .waitForElementVisible('#app > *', 1000) + .assert.containsText('#beforeEach', '3') + .assert.containsText('#beforeResolve', '3') + .assert.containsText('#afterEach', '3') + .assert.containsText('#view', 'foo') + + .end() + } +}