From 3f4be666072fb2dd3bd3947b07df56834ae81ec1 Mon Sep 17 00:00:00 2001 From: !z Date: Thu, 13 Dec 2018 18:21:42 +0400 Subject: [PATCH 1/3] feat(reload): public function and _force checks --- src/history/base.js | 5 +++-- src/index.js | 12 ++++++++++++ src/util/location.js | 8 +++++++- src/util/route.js | 3 +++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/history/base.js b/src/history/base.js index 5b6f199c6..6260d3978 100644 --- a/src/history/base.js +++ b/src/history/base.js @@ -97,8 +97,9 @@ export class History { } onAbort && onAbort(err) } - if ( - isSameRoute(route, current) && + if (isSameRoute(route, current) && + // case for public function "reload" + !route._force && // in the case the route map has been dynamically appended to route.matched.length === current.matched.length ) { diff --git a/src/index.js b/src/index.js index a1a7b8507..03483d4cc 100644 --- a/src/index.js +++ b/src/index.js @@ -142,6 +142,18 @@ export default class VueRouter { this.history.push(location, onComplete, onAbort) } + reload (location: RawLocation) { + const current = this.history.current + this.history.push({ + _force: true, + hash: current.hash, + name: current.name, + path: current.path, + params: current.params, + query: current.query + }) + } + replace (location: RawLocation, onComplete?: Function, onAbort?: Function) { this.history.replace(location, onComplete, onAbort) } diff --git a/src/util/location.js b/src/util/location.js index 364e6fc0c..7a12d556c 100644 --- a/src/util/location.js +++ b/src/util/location.js @@ -53,10 +53,16 @@ export function normalizeLocation ( hash = `#${hash}` } - return { + const result = { _normalized: true, path, query, hash } + // check force + if (next._force) { + result._force = true + } + + return result } diff --git a/src/util/route.js b/src/util/route.js index 54a91a738..02a35c37c 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -31,6 +31,9 @@ export function createRoute ( if (redirectedFrom) { route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery) } + if (location._force) { + route._force = true + } return Object.freeze(route) } From 67b0a87ec6e7aeeb34b013045eefcefb9a1a6fb9 Mon Sep 17 00:00:00 2001 From: !z Date: Thu, 13 Dec 2018 18:49:39 +0400 Subject: [PATCH 2/3] test(examples): "Public reload method" page /reload --- examples/index.html | 1 + examples/reload/app.js | 142 +++++++++++++++++++++++++++++++++++++ examples/reload/index.html | 6 ++ 3 files changed, 149 insertions(+) create mode 100644 examples/reload/app.js create mode 100644 examples/reload/index.html diff --git a/examples/index.html b/examples/index.html index f2bdf7225..90a1018c8 100644 --- a/examples/index.html +++ b/examples/index.html @@ -25,6 +25,7 @@

Vue Router Examples

  • Auth Flow
  • Discrete Components
  • Nested Routers
  • +
  • Public reload method
  • diff --git a/examples/reload/app.js b/examples/reload/app.js new file mode 100644 index 000000000..ae1e5f590 --- /dev/null +++ b/examples/reload/app.js @@ -0,0 +1,142 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' +import Post from '../data-fetching/Post.vue' + +Vue.use(VueRouter) + +const Home = { template: '
    home
    ' } +const Foo = { template: '
    foo
    ' } +const Bar = { template: '
    bar
    ' } + +function guardRoute (to, from, next) { + if (window.confirm(`Navigate to ${to.path}?`)) { + next() + } else if (window.confirm(`Redirect to /baz?`)) { + next('/baz') + } else { + next(false) + } +} + +// Baz implements an in-component beforeRouteLeave hook +const Baz = { + data () { + return { saved: false } + }, + template: ` +
    +

    baz ({{ saved ? 'saved' : 'not saved' }})

    + +
    + `, + beforeRouteLeave (to, from, next) { + if (this.saved || window.confirm('Not saved, are you sure you want to navigate away?')) { + next() + } else { + next(false) + } + } +} + +// Baz implements an in-component beforeRouteEnter hook +const Qux = { + data () { + return { + msg: null + } + }, + template: `
    {{ msg }}
    `, + beforeRouteEnter (to, from, next) { + // Note that enter hooks do not have access to `this` + // because it is called before the component is even created. + // However, we can provide a callback to `next` which will + // receive the vm instance when the route has been confirmed. + // + // simulate an async data fetch. + // this pattern is useful when you want to stay at current route + // and only switch after the data has been fetched. + setTimeout(() => { + next(vm => { + vm.msg = 'Qux' + }) + }, 300) + } +} + +// Quux implements an in-component beforeRouteUpdate hook. +// this hook is called when the component is reused, but the route is updated. +// For example, when navigating from /quux/1 to /quux/2. +const Quux = { + data () { + return { + prevId: 0 + } + }, + template: `
    id:{{ $route.params.id }} prevId:{{ prevId }}
    `, + beforeRouteUpdate (to, from, next) { + this.prevId = from.params.id + next() + } +} + +const router = new VueRouter({ + mode: 'history', + base: __dirname, + routes: [ + { path: '/', component: Home }, + + // post with transitions + { path: '/post/:id', component: Post }, + + // inline guard + { path: '/foo', component: Foo, beforeEnter: guardRoute }, + + // using meta properties on the route config + // and check them in a global before hook + { path: '/bar', component: Bar, meta: { needGuard: true }}, + + // Baz implements an in-component beforeRouteLeave hook + { path: '/baz', component: Baz }, + + // Qux implements an in-component beforeRouteEnter hook + { path: '/qux', component: Qux }, + + // in-component beforeRouteEnter hook for async components + { path: '/qux-async', component: resolve => { + setTimeout(() => { + resolve(Qux) + }, 0) + } }, + + // in-component beforeRouteUpdate hook + { path: '/quux/:id', component: Quux } + ] +}) + +router.beforeEach((to, from, next) => { + if (to.matched.some(m => m.meta.needGuard)) { + guardRoute(to, from, next) + } else { + next() + } +}) + +new Vue({ + router, + template: ` +
    +

    reload() behaviors

    + +
      +
    • /
    • +
    • /post/1
    • +
    • /foo
    • +
    • /bar
    • +
    • /baz
    • +
    • /quux/1
    • +
    • /quux/2
    • +
    + +
    + ` +}).$mount('#app') diff --git a/examples/reload/index.html b/examples/reload/index.html new file mode 100644 index 000000000..cd4327611 --- /dev/null +++ b/examples/reload/index.html @@ -0,0 +1,6 @@ + + +← Examples index +
    + + From e6b6c4082b155f51ff901a9404dbeb72ce1c4733 Mon Sep 17 00:00:00 2001 From: !z Date: Thu, 13 Dec 2018 19:42:46 +0400 Subject: [PATCH 3/3] chore(test): fixes --- flow/declarations.js | 1 + src/index.js | 19 +++++++++---------- src/util/location.js | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/flow/declarations.js b/flow/declarations.js index 942aa73bf..731c3983d 100644 --- a/flow/declarations.js +++ b/flow/declarations.js @@ -91,6 +91,7 @@ declare type Location = { declare type RawLocation = string | Location declare type Route = { + _force?: boolean; path: string; name: ?string; hash: string; diff --git a/src/index.js b/src/index.js index 03483d4cc..05dcc3c42 100644 --- a/src/index.js +++ b/src/index.js @@ -142,16 +142,15 @@ export default class VueRouter { this.history.push(location, onComplete, onAbort) } - reload (location: RawLocation) { - const current = this.history.current - this.history.push({ - _force: true, - hash: current.hash, - name: current.name, - path: current.path, - params: current.params, - query: current.query - }) + reload () { + const { current } = this.history + const result: Object = { _force: true } + if (current.hash) result.hash = current.hash + if (current.path) result.path = current.path + if (current.params) result.params = current.params + if (current.query) result.query = current.query + + this.history.push(result) } replace (location: RawLocation, onComplete?: Function, onAbort?: Function) { diff --git a/src/util/location.js b/src/util/location.js index 7a12d556c..64d5d64a7 100644 --- a/src/util/location.js +++ b/src/util/location.js @@ -53,7 +53,7 @@ export function normalizeLocation ( hash = `#${hash}` } - const result = { + const result: Object = { _normalized: true, path, query,