Skip to content

Commit 7cb3e4e

Browse files
committed
feat: add beforeRouteUpdate hook (close #938)
1 parent e08a612 commit 7cb3e4e

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

src/history/base.js

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export class History {
5555
}
5656

5757
const {
58+
updated,
5859
deactivated,
5960
activated
6061
} = resolveQueue(this.current.matched, route.matched)
@@ -64,7 +65,9 @@ export class History {
6465
extractLeaveGuards(deactivated),
6566
// global before hooks
6667
this.router.beforeHooks,
67-
// enter guards
68+
// in-component update hooks
69+
extractUpdateHooks(updated),
70+
// in-config enter guards
6871
activated.map(m => m.beforeEnter),
6972
// async components
7073
resolveAsyncComponents(activated)
@@ -93,9 +96,8 @@ export class History {
9396

9497
runQueue(queue, iterator, () => {
9598
const postEnterCbs = []
96-
const enterGuards = extractEnterGuards(activated, postEnterCbs, () => {
97-
return this.current === route
98-
})
99+
const isValid = () => this.current === route
100+
const enterGuards = extractEnterGuards(activated, postEnterCbs, isValid)
99101
// wait until async components are resolved before
100102
// extracting in-component enter guards
101103
runQueue(enterGuards, iterator, () => {
@@ -145,6 +147,7 @@ function resolveQueue (
145147
current: Array<RouteRecord>,
146148
next: Array<RouteRecord>
147149
): {
150+
updated: Array<RouteRecord>,
148151
activated: Array<RouteRecord>,
149152
deactivated: Array<RouteRecord>
150153
} {
@@ -156,11 +159,29 @@ function resolveQueue (
156159
}
157160
}
158161
return {
162+
updated: next.slice(0, i),
159163
activated: next.slice(i),
160164
deactivated: current.slice(i)
161165
}
162166
}
163167

168+
function extractGuards (
169+
records: Array<RouteRecord>,
170+
name: string,
171+
bind: Function,
172+
reverse?: boolean
173+
): Array<?Function> {
174+
const guards = flatMapComponents(records, (def, instance, match, key) => {
175+
const guard = extractGuard(def, name)
176+
if (guard) {
177+
return Array.isArray(guard)
178+
? guard.map(guard => bind(guard, instance, match, key))
179+
: bind(guard, instance, match, key)
180+
}
181+
})
182+
return flatten(reverse ? guards.reverse() : guards)
183+
}
184+
164185
function extractGuard (
165186
def: Object | Function,
166187
key: string
@@ -172,46 +193,35 @@ function extractGuard (
172193
return def.options[key]
173194
}
174195

175-
function extractLeaveGuards (matched: Array<RouteRecord>): Array<?Function> {
176-
return flatten(flatMapComponents(matched, (def, instance) => {
177-
const guard = extractGuard(def, 'beforeRouteLeave')
178-
if (guard) {
179-
return Array.isArray(guard)
180-
? guard.map(guard => wrapLeaveGuard(guard, instance))
181-
: wrapLeaveGuard(guard, instance)
182-
}
183-
}).reverse())
196+
function extractLeaveGuards (deactivated: Array<RouteRecord>): Array<?Function> {
197+
return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)
184198
}
185199

186-
function wrapLeaveGuard (
187-
guard: NavigationGuard,
188-
instance: _Vue
189-
): NavigationGuard {
190-
return function routeLeaveGuard () {
200+
function extractUpdateHooks (updated: Array<RouteRecord>): Array<?Function> {
201+
return extractGuards(updated, 'beforeRouteUpdate', bindGuard)
202+
}
203+
204+
function bindGuard (guard: NavigationGuard, instance: _Vue): NavigationGuard {
205+
return function boundRouteGuard () {
191206
return guard.apply(instance, arguments)
192207
}
193208
}
194209

195210
function extractEnterGuards (
196-
matched: Array<RouteRecord>,
211+
activated: Array<RouteRecord>,
197212
cbs: Array<Function>,
198213
isValid: () => boolean
199214
): Array<?Function> {
200-
return flatten(flatMapComponents(matched, (def, _, match, key) => {
201-
const guard = extractGuard(def, 'beforeRouteEnter')
202-
if (guard) {
203-
return Array.isArray(guard)
204-
? guard.map(guard => wrapEnterGuard(guard, cbs, match, key, isValid))
205-
: wrapEnterGuard(guard, cbs, match, key, isValid)
206-
}
207-
}))
215+
return extractGuards(activated, 'beforeRouteEnter', (guard, _, match, key) => {
216+
return bindEnterGuard(guard, match, key, cbs, isValid)
217+
})
208218
}
209219

210-
function wrapEnterGuard (
220+
function bindEnterGuard (
211221
guard: NavigationGuard,
212-
cbs: Array<Function>,
213222
match: RouteRecord,
214223
key: string,
224+
cbs: Array<Function>,
215225
isValid: () => boolean
216226
): NavigationGuard {
217227
return function routeEnterGuard (to, from, next) {

types/vue.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ declare module "vue/types/options" {
1818
router?: VueRouter;
1919
beforeRouteEnter?: NavigationGuard;
2020
beforeRouteLeave?: NavigationGuard;
21+
beforeRouteUpdate?: NavigationGuard;
2122
}
2223
}

0 commit comments

Comments
 (0)