]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(abstract): listen for navigation
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 5 Jun 2019 13:35:17 +0000 (15:35 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 5 Jun 2019 13:35:17 +0000 (15:35 +0200)
__tests__/abstract.spec.js
src/history/abstract.ts

index c490457c597aedc8735fc18940a09ed452b91c37..24aeb525e4eed0835b8ec2b361e40b04d479ff61 100644 (file)
@@ -64,6 +64,7 @@ describe('Abstract/in memory history', () => {
   it('saves forward information', () => {})
 
   it('can replace a location', () => {})
+
   it('can simulate a navigation', () => {})
 
   it('add entries to the queue', () => {
@@ -128,4 +129,36 @@ describe('Abstract/in memory history', () => {
     expect(history.queue).toHaveLength(2)
     expect(history.location).toEqual(normaliezedLoc2)
   })
+
+  it('can listen to navigations', () => {
+    const history = new AbstractHistory()
+    const spy = jest.fn()
+    history.listen(spy)
+    history.push(loc)
+    history.back()
+    expect(spy).toHaveBeenCalledTimes(1)
+    expect(spy).toHaveBeenCalledWith(START, normaliezedLoc, { type: 'back' })
+    history.forward()
+    expect(spy).toHaveBeenCalledTimes(2)
+    expect(spy).toHaveBeenLastCalledWith(normaliezedLoc, START, {
+      type: 'forward',
+    })
+  })
+
+  it('can stop listening to navigation', () => {
+    const history = new AbstractHistory()
+    const spy = jest.fn()
+    const spy2 = jest.fn()
+    // remove right away
+    history.listen(spy)()
+    const remove = history.listen(spy2)
+    history.push(loc)
+    history.back()
+    expect(spy).not.toHaveBeenCalled()
+    expect(spy2).toHaveBeenCalledTimes(1)
+    remove()
+    history.forward()
+    expect(spy).not.toHaveBeenCalled()
+    expect(spy2).toHaveBeenCalledTimes(1)
+  })
 })
index 2b318321892ac4205fa4bc9d28c3d3e246e79054..c0434f1efb23c91e540e128c252371c337720c78 100644 (file)
@@ -1,5 +1,10 @@
 // import consola from 'consola'
-import { BaseHistory, HistoryLocation, HistoryLocationNormalized } from './base'
+import {
+  BaseHistory,
+  HistoryLocation,
+  HistoryLocationNormalized,
+  NavigationType,
+} from './base'
 import { NavigationCallback, HistoryState, START } from './base'
 
 // const cs = consola.withTag('abstract')
@@ -7,6 +12,7 @@ import { NavigationCallback, HistoryState, START } from './base'
 export class AbstractHistory extends BaseHistory {
   // private _listeners: NavigationCallback[] = []
   private teardowns: Array<() => void> = []
+  private listeners: NavigationCallback[] = []
   public queue: HistoryLocationNormalized[] = [START]
   public position: number = 0
 
@@ -25,7 +31,11 @@ export class AbstractHistory extends BaseHistory {
   }
 
   listen(callback: NavigationCallback) {
-    return () => {}
+    this.listeners.push(callback)
+    return () => {
+      const index = this.listeners.indexOf(callback)
+      if (index > -1) this.listeners.splice(index, 1)
+    }
   }
 
   get location() {
@@ -48,15 +58,30 @@ export class AbstractHistory extends BaseHistory {
   }
 
   back() {
+    const from = this.location
     if (this.position > 0) this.position--
+    this.triggerListeners(this.location, from, { type: NavigationType.back })
   }
 
   forward() {
+    const from = this.location
     if (this.position < this.queue.length - 1) this.position++
+    this.triggerListeners(this.location, from, { type: NavigationType.forward })
   }
 
   destroy() {
     for (const teardown of this.teardowns) teardown()
     this.teardowns = []
   }
+
+  private triggerListeners(
+    to: HistoryLocationNormalized,
+    from: HistoryLocationNormalized,
+    { type }: { type: NavigationType }
+  ): void {
+    const info = { type }
+    for (let callback of this.listeners) {
+      callback(to, from, info)
+    }
+  }
 }