From: Eduardo San Martin Morote Date: Mon, 11 Feb 2019 22:55:35 +0000 (+0100) Subject: improve history class X-Git-Tag: v4.0.0-alpha.0~477 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3a94784b0f8ae048d41589aa94eefea8698467d;p=thirdparty%2Fvuejs%2Frouter.git improve history class --- diff --git a/src/history/base.ts b/src/history/base.ts index 8633930a..28b6d548 100644 --- a/src/history/base.ts +++ b/src/history/base.ts @@ -1,22 +1,41 @@ -import { START, HistoryLocation } from '../types/index' -export interface NavigationCallback { - (to: HistoryLocation, from: HistoryLocation): void -} +import { + START, + HistoryLocation, + NavigationCallback, + RemoveListener, +} from '../types/index' export default abstract class BaseHistory { // previousState: object - location: HistoryLocation + location: HistoryLocation = START + + /** + * Sync source with a different location. + * Adds an entry to the history + * @param to URL to go to + */ abstract push(to: HistoryLocation): void + + /** + * Syncs source with a different location + * Replaces current entry in the history + * @param to URL to go to + */ abstract replace(to: HistoryLocation): void - abstract listen(callback: NavigationCallback): Function + + /** + * Notifies back whenever the location changes due to user interactions + * outside of the applicaiton. For example, going back/forward on a + * web browser + * @param callback callback to be called whenever the route changes + * @returns + */ + abstract listen(callback: NavigationCallback): RemoveListener + /** - * ensure the current location using the external source - * for example, in HTML5 and hash history, that would be + * ensure the current location matches the external source + * For example, in HTML5 and hash history, that would be * location.pathname */ abstract ensureLocation(): void - - constructor() { - this.location = START - } } diff --git a/src/history/html5.ts b/src/history/html5.ts index ccd63e68..ca666827 100644 --- a/src/history/html5.ts +++ b/src/history/html5.ts @@ -1,8 +1,12 @@ -import BaseHistory, { NavigationCallback } from './base' -import { HistoryLocation } from '../types/index' +import BaseHistory from './base' +import { HistoryLocation, NavigationCallback } from '../types/index' export default class HTML5History extends BaseHistory { private history = window.history + private _popStateListener: + | null + | ((this: Window, ev: PopStateEvent) => any) = null + constructor() { super() } @@ -14,9 +18,11 @@ export default class HTML5History extends BaseHistory { replace(to: HistoryLocation) { if (to === this.location) return + console.log('replace', this.location, to) this.history.replaceState( { - ...(this.history.state || {}), + replacedState: this.history.state || {}, + from: this.location, to, }, '', @@ -26,27 +32,30 @@ export default class HTML5History extends BaseHistory { } push(to: HistoryLocation) { - // TODO resolve url - // TODO compare current location to prevent navigation + // TODO: resolve url + // TODO: compare current location to prevent navigation if (to === this.location) return const state = { from: this.location, to, } - console.log('push', state) + console.log('push', this.location, to) this.history.pushState(state, '', to) this.location = to } - listen(callback: NavigationCallback): Function { - window.addEventListener('popstate', ({ state }) => { + listen(callback: NavigationCallback) { + this._popStateListener = ({ state }) => { const from = this.location // we have the state from the old entry, not the current one being removed - // TODO correctly parse pathname + // TODO: correctly parse pathname this.location = state ? state.to : window.location.pathname callback(this.location, from) - }) + } + window.addEventListener('popstate', this._popStateListener) - return () => {} + return () => { + window.removeEventListener('popstate', this._popStateListener!) + } } }