From 47a85aab743749107d9b6773d2d7bfe135df0908 Mon Sep 17 00:00:00 2001 From: nilibing <nilibing@xindong.com> Date: Tue, 26 Oct 2021 16:18:13 +0800 Subject: [PATCH] feat: ability to check push vs replace in navigation guard issue #1620 pull request #1906 --- examples/index.html | 1 + examples/push-or-replace/app.js | 77 +++++++++++++++++++++++++++++ examples/push-or-replace/index.html | 6 +++ src/history/hash.js | 6 +++ src/history/html5.js | 6 +++ src/util/location.js | 3 +- src/util/route.js | 1 + 7 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 examples/push-or-replace/app.js create mode 100644 examples/push-or-replace/index.html diff --git a/examples/index.html b/examples/index.html index 5f2cd4f32..535035ad6 100644 --- a/examples/index.html +++ b/examples/index.html @@ -27,6 +27,7 @@ <h1>Vue Router Examples</h1> <li><a href="auth-flow">Auth Flow</a></li> <li><a href="discrete-components">Discrete Components</a></li> <li><a href="nested-router">Nested Routers</a></li> + <li><a href="push-or-replace">Push Or Replace</a></li> <li><a href="keepalive-view">Keepalive View</a></li> <li><a href="multi-app">Multiple Apps</a></li> <li><a href="restart-app">Restart App</a></li> diff --git a/examples/push-or-replace/app.js b/examples/push-or-replace/app.js new file mode 100644 index 000000000..82f96d3c0 --- /dev/null +++ b/examples/push-or-replace/app.js @@ -0,0 +1,77 @@ +import Vue from 'vue' +import VueRouter from 'vue-router' + +Vue.use(VueRouter) + +const store = Vue.observable({ + replace: false, + time: new Date().getTime() +}) + +const computed = { + replace () { + return store.replace + }, + time () { + return store.time + } +} + +const Home = { computed, template: '<div>home {{replace}} {{time}}</div>' } +const Page = { computed, template: '<div>page {{replace}} {{time}}</div>' } +const Detail = { computed, template: '<div>detail {{replace}} {{time}}</div>' } + +const router = new VueRouter({ + mode: 'history', + base: __dirname, + routes: [ + { path: '/', component: Home }, + + { path: '/page', component: Page }, + + { path: '/detail', component: Detail } + + ] +}) + +// User can check the replace type in navigation guard, and do anything they want. +router.beforeEach((to, from, next) => { + store.replace = to.replace + store.time = new Date().getTime() + next() +}) + +new Vue({ + router, + template: ` + <div id="app"> + <h1>Push Or Replace</h1> + <p>User can check the replace type in navigation guard, and do anything they want.</p> + <pre> +router.beforeEach((to, from, next) => { + if (to.replace) { + to.query.replace = true + } + else { + to.query.replace = false + } + if (to && to.query && !to.query.time) { + to.query.time = new Date().getTime() + next(to) + } else { + next() + } +}) + </pre> + <ul> + <li><router-link to="/">/</router-link></li> + <li><router-link to="/page">/page</router-link> ( push )</li> + <li><a @click="$router.push('/page')">/page</a> $router.push('/page') </li> + <li><router-link to="/detail" replace>/detail</router-link> ( replace )</li> + <li><a @click="$router.replace('/detail')">/detail</a> $router.replace('/detail') </li> + <li><a @click="$router.go(-1)">back</a> $router.go(-1) </li> + </ul> + <router-view class="view"></router-view> + </div> + ` +}).$mount('#app') diff --git a/examples/push-or-replace/index.html b/examples/push-or-replace/index.html new file mode 100644 index 000000000..0b88284f9 --- /dev/null +++ b/examples/push-or-replace/index.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<link rel="stylesheet" href="/global.css"> +<a href="/">← Examples index</a> +<div id="app"></div> +<script src="/__build__/shared.chunk.js"></script> +<script src="/__build__/push-or-replace.js"></script> diff --git a/src/history/hash.js b/src/history/hash.js index e0ddf2d7c..4b5bccf6d 100644 --- a/src/history/hash.js +++ b/src/history/hash.js @@ -71,6 +71,12 @@ export class HashHistory extends History { replace (location: RawLocation, onComplete?: Function, onAbort?: Function) { const { current: fromRoute } = this + if (typeof location === 'string') { + location = { path: location } + } + if (typeof location === 'object') { + (location: Object).replace = true + } this.transitionTo( location, route => { diff --git a/src/history/html5.js b/src/history/html5.js index faaa02fcd..058d70846 100644 --- a/src/history/html5.js +++ b/src/history/html5.js @@ -66,6 +66,12 @@ export class HTML5History extends History { replace (location: RawLocation, onComplete?: Function, onAbort?: Function) { const { current: fromRoute } = this + if (typeof location === 'string') { + location = { path: location } + } + if (typeof location === 'object') { + (location: Object).replace = true + } this.transitionTo(location, route => { replaceState(cleanPath(this.base + route.fullPath)) handleScroll(this.router, route, fromRoute, false) diff --git a/src/util/location.js b/src/util/location.js index fb98d4537..a2f72f817 100644 --- a/src/util/location.js +++ b/src/util/location.js @@ -64,6 +64,7 @@ export function normalizeLocation ( _normalized: true, path, query, - hash + hash, + replace: !!next.replace } } diff --git a/src/util/route.js b/src/util/route.js index 9d8e31cd1..9fdda7a7f 100644 --- a/src/util/route.js +++ b/src/util/route.js @@ -23,6 +23,7 @@ export function createRoute ( meta: (record && record.meta) || {}, path: location.path || '/', hash: location.hash || '', + replace: !!location.replace, query, params: location.params || {}, fullPath: getFullPath(location, stringifyQuery),