]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
improve history class
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 11 Feb 2019 22:55:35 +0000 (23:55 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 11 Feb 2019 22:55:35 +0000 (23:55 +0100)
src/history/base.ts
src/history/html5.ts

index 8633930ac70c2322f555d752f5bf393e895bc821..28b6d548a27cc82a9e0978e71f2c840f528c242e 100644 (file)
@@ -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
-  }
 }
index ccd63e68ed343fa269295d11e472edb71d416eaf..ca666827a1ea76341fadcb8e8deebe6aaeeaa793 100644 (file)
@@ -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!)
+    }
   }
 }