From a023abe4170ef137d05948eb2b09024e4acb56d2 Mon Sep 17 00:00:00 2001 From: bailnl Date: Fri, 18 Oct 2019 00:07:07 +0800 Subject: [PATCH] feat: add destroy method, remove event listener on destroy --- src/history/base.js | 6 ++++++ src/history/hash.js | 38 +++++++++++++++++++++----------------- src/history/html5.js | 12 +++++++++--- src/index.js | 4 ++++ src/util/scroll.js | 9 +++++++-- 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index 2b12e1967..e1e6526a8 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -23,6 +23,7 @@ export class History { readyCbs: Array readyErrorCbs: Array errorCbs: Array + removeEventListenerCbs: Array // implemented by sub-classes +go: (n: number) => void @@ -41,6 +42,7 @@ export class History { this.readyCbs = [] this.readyErrorCbs = [] this.errorCbs = [] + this.removeEventListenerCbs = [] } listen (cb: Function) { @@ -208,6 +210,10 @@ export class History { hook && hook(route, prev) }) } + + destroy () { + this.removeEventListenerCbs.forEach(cb => { cb() }) + } } function normalizeBase (base: ?string): string { diff --git a/src/history/hash.js b/src/history/hash.js index 25a670fcb..895418da1 100644 --- a/src/history/hash.js +++ b/src/history/hash.js @@ -25,26 +25,30 @@ export class HashHistory extends History { const supportsScroll = supportsPushState && expectScroll if (supportsScroll) { - setupScroll() + const uninstall = setupScroll() + this.removeEventListenerCbs.push(uninstall) } - window.addEventListener( - supportsPushState ? 'popstate' : 'hashchange', - () => { - const current = this.current - if (!ensureSlash()) { - return - } - this.transitionTo(getHash(), route => { - if (supportsScroll) { - handleScroll(this.router, route, current, true) - } - if (!supportsPushState) { - replaceHash(route.fullPath) - } - }) + const eventName = supportsPushState ? 'popstate' : 'hashchange' + const listener = () => { + const current = this.current + if (!ensureSlash()) { + return } - ) + this.transitionTo(getHash(), route => { + if (supportsScroll) { + handleScroll(this.router, route, current, true) + } + if (!supportsPushState) { + replaceHash(route.fullPath) + } + }) + } + window.addEventListener(eventName, listener) + const uninstall = () => { + window.removeEventListener(eventName, listener) + } + this.removeEventListenerCbs.push(uninstall) } push (location: RawLocation, onComplete?: Function, onAbort?: Function) { diff --git a/src/history/html5.js b/src/history/html5.js index e1cdba97d..e8813aee5 100644 --- a/src/history/html5.js +++ b/src/history/html5.js @@ -15,11 +15,12 @@ export class HTML5History extends History { const supportsScroll = supportsPushState && expectScroll if (supportsScroll) { - setupScroll() + const uninstall = setupScroll() + this.removeEventListenerCbs.push(uninstall) } const initLocation = getLocation(this.base) - window.addEventListener('popstate', e => { + const listener = e => { const current = this.current // Avoiding first `popstate` event dispatched in some browsers but first @@ -34,7 +35,12 @@ export class HTML5History extends History { handleScroll(router, route, current, true) } }) - }) + } + window.addEventListener('popstate', listener) + const uninstall = () => { + window.removeEventListener('popstate', listener) + } + this.removeEventListenerCbs.push(uninstall) } go (n: number) { diff --git a/src/index.js b/src/index.js index e95ace6d1..2e21c8ff8 100644 --- a/src/index.js +++ b/src/index.js @@ -239,6 +239,10 @@ export default class VueRouter { this.history.transitionTo(this.history.getCurrentLocation()) } } + + destroy () { + this.history.destroy() + } } function registerHook (list: Array, fn: Function): Function { diff --git a/src/util/scroll.js b/src/util/scroll.js index 683adc456..73e5d6461 100644 --- a/src/util/scroll.js +++ b/src/util/scroll.js @@ -15,12 +15,17 @@ export function setupScroll () { const protocolAndPath = window.location.protocol + '//' + window.location.host const absolutePath = window.location.href.replace(protocolAndPath, '') window.history.replaceState({ key: getStateKey() }, '', absolutePath) - window.addEventListener('popstate', e => { + const listener = e => { saveScrollPosition() if (e.state && e.state.key) { setStateKey(e.state.key) } - }) + } + window.addEventListener('popstate', listener) + + return function uninstall () { + window.removeEventListener('popstate', listener) + } } export function handleScroll (