Skip to content

Commit

Permalink
feat(history): Reset history.current when all apps are destroyed (#3298)
Browse files Browse the repository at this point in the history
* feat(history): Reset history.current when all apps are destroyed

* test(history): adding restart-app test

* refactor: split History.teardown method

* refactor: general History.teardown method
  • Loading branch information
nightnei committed Aug 31, 2020
1 parent af6e7a0 commit c69ff7b
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 6 deletions.
1 change: 1 addition & 0 deletions examples/index.html
Expand Up @@ -29,6 +29,7 @@ <h1>Vue Router Examples</h1>
<li><a href="nested-router">Nested Routers</a></li>
<li><a href="keepalive-view">Keepalive View</a></li>
<li><a href="multi-app">Multiple Apps</a></li>
<li><a href="restart-app">Restart App</a></li>
</ul>
</body>
</html>
66 changes: 66 additions & 0 deletions examples/restart-app/app.js
@@ -0,0 +1,66 @@
import Vue from 'vue'
import VueRouter from 'vue-router'

const Home = { template: '<div>home</div>' }
const Foo = { template: '<div>foo</div>' }

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: `
<div id="app">
<h1>Hello "Restart-app"</h1>
<ul>
<li><router-link to="/">Go to Home</router-link></li>
<li><router-link to="/foo">Go to Foo</router-link></li>
</ul>
<router-view id="view"></router-view>
</div>
`
}).$mount('#app')
})

unmountEl.addEventListener('click', () => {
vueInstance.$destroy()
vueInstance.$el.innerHTML = ''
})
21 changes: 21 additions & 0 deletions examples/restart-app/index.html
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<link rel="stylesheet" href="/global.css">
<a href="/">&larr; Examples index</a>

<hr />

<button id="mount">mount</button>
<button id="unmount">unmount</button>

<hr />

Count beforeEach: <span id="beforeEach"></span><br />
Count beforeResolve: <span id="beforeResolve"></span><br />
Count afterEach: <span id="afterEach"></span><br />

<hr />

<div id="app"></div>

<script src="/__build__/shared.chunk.js"></script>
<script src="/__build__/restart-app.js"></script>
9 changes: 8 additions & 1 deletion src/history/base.js
Expand Up @@ -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
}
}

Expand Down
6 changes: 1 addition & 5 deletions src/index.js
Expand Up @@ -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
Expand Down
45 changes: 45 additions & 0 deletions 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()
}
}

0 comments on commit c69ff7b

Please sign in to comment.