From: Eduardo San Martin Morote Date: Thu, 11 Apr 2019 14:59:54 +0000 (+0200) Subject: refactor history state X-Git-Tag: v4.0.0-alpha.0~462 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f7983181b678aa8f730b5e9f1b90c0bc11090b7;p=thirdparty%2Fvuejs%2Frouter.git refactor history state --- diff --git a/src/history/base.ts b/src/history/base.ts index 8c396336..eb6d72c3 100644 --- a/src/history/base.ts +++ b/src/history/base.ts @@ -11,6 +11,7 @@ type HistoryStateValue = | string | number | boolean + | null | HistoryState | HistoryStateArray export interface HistoryState { diff --git a/src/history/html5.ts b/src/history/html5.ts index 90d69a92..880a5340 100644 --- a/src/history/html5.ts +++ b/src/history/html5.ts @@ -12,6 +12,28 @@ const cs = consola.withTag('html5') type PopStateListener = (this: Window, ev: PopStateEvent) => any +interface StateEntry { + back: HistoryLocation | null + current: HistoryLocation + forward: HistoryLocation | null + replaced: boolean +} + +// TODO: pretty useless right now except for typing +function buildState( + back: HistoryLocation | null, + current: HistoryLocation, + forward: HistoryLocation | null, + replaced: boolean = false +): StateEntry { + return { + back, + current, + forward, + replaced, + } +} + export class HTML5History extends BaseHistory { private history = window.history private _popStateListeners: PopStateListener[] = [] @@ -20,36 +42,22 @@ export class HTML5History extends BaseHistory { constructor() { super() - } - - // TODO: is this necessary - ensureLocation() { const to = buildFullPath() - cs.log('ensureLocation', to) - this.history.replaceState( - { - _back: null, - _current: to, - _forward: null, - }, - '', - to - ) + cs.log('created', to) + this.history.replaceState(buildState(null, to, null), '', to) this.location = to } + // TODO: is this necessary + ensureLocation() {} + replace(to: HistoryLocation) { if (to === this.location) return cs.info('replace', this.location, to) this.history.replaceState( - { - // TODO: this should be user's responsibility - // _replacedState: this.history.state || null, - _back: this.location, - _current: to, - _forward: null, - _replaced: true, - }, + // TODO: this should be user's responsibility + // _replacedState: this.history.state || null, + buildState(this.history.state.back, to, null, true), '', to ) @@ -59,19 +67,19 @@ export class HTML5History extends BaseHistory { push(to: HistoryLocation, data?: HistoryState) { // replace current entry state to add the forward value this.history.replaceState( - { - ...this.history.state, - _forward: to, - }, + buildState( + this.history.state.back, + this.history.state.current, + to, + this.history.state.replaced + ), '' ) // TODO: compare current location to prevent navigation // NEW NOTE: I think it shouldn't be history responsibility to check that // if (to === this.location) return const state = { - _back: this.location, - _current: to, - _forward: null, + ...buildState(this.location, to, null), ...data, } cs.info('push', this.location, '->', to, 'with state', state) @@ -81,8 +89,7 @@ export class HTML5History extends BaseHistory { listen(callback: NavigationCallback) { // state is the same as history.state - const handler: PopStateListener = ({ state }) => { - cs.log(this) + const handler: PopStateListener = ({ state }: { state: StateEntry }) => { cs.info('popstate fired', { state, location: this.location, @@ -90,12 +97,10 @@ export class HTML5History extends BaseHistory { const from = this.location // we have the state from the old entry, not the current one being removed // TODO: correctly parse pathname - this.location = state ? state._current : buildFullPath + this.location = state ? state.current : buildFullPath() callback(this.location, from, { type: - from === state._forward - ? NavigationType.back - : NavigationType.forward, + from === state.forward ? NavigationType.back : NavigationType.forward, }) } diff --git a/src/router.ts b/src/router.ts index 52d985fa..50c78bf5 100644 --- a/src/router.ts +++ b/src/router.ts @@ -19,9 +19,14 @@ export class Router { constructor(options: RouterOptions) { this.history = options.history - this.history.ensureLocation() + // this.history.ensureLocation() this.matcher = new RouterMatcher(options.routes) + + this.history.listen((to, from, info) => { + // TODO: check navigation guards + this.currentRoute = this.matcher.resolve(to, this.currentRoute) + }) } /**