1- import { getCurrentInstance , shallowReactive , effectScope , onUnmounted } from 'vue'
1+ import {
2+ getCurrentInstance ,
3+ shallowReactive ,
4+ effectScope ,
5+ onUnmounted
6+ } from 'vue'
27
38export function useRouter ( ) {
49 const i = getCurrentInstance ( )
@@ -17,8 +22,8 @@ export function useRoute () {
1722
1823 const root = i . proxy . $root
1924 if ( ! root . _$route ) {
20- const route = effectScope ( true ) . run (
21- ( ) => shallowReactive ( Object . assign ( { } , root . $router . currentRoute ) )
25+ const route = effectScope ( true ) . run ( ( ) =>
26+ shallowReactive ( Object . assign ( { } , root . $router . currentRoute ) )
2227 )
2328 root . _$route = route
2429
@@ -39,33 +44,68 @@ export function onBeforeRouteUpdate (guard) {
3944 throwNoCurrentInstance ( 'onBeforeRouteUpdate' )
4045 }
4146
47+ return useFilteredGuard ( guard , isUpdateNavigation )
48+ }
49+
50+ function useFilteredGuard ( guard , fn ) {
51+ const i = getCurrentInstance ( )
4252 const router = useRouter ( )
4353
4454 let target = i . proxy
4555 // find the nearest routerview to know the depth
46- while ( target && target . $vnode && target . $vnode . data && target . $vnode . data . routerViewDepth == null ) {
56+ while (
57+ target &&
58+ target . $vnode &&
59+ target . $vnode . data &&
60+ target . $vnode . data . routerViewDepth == null
61+ ) {
4762 target = target . $parent
4863 }
4964
50- const depth = target && target . $vnode && target . $vnode . data ? target . $vnode . data . routerViewDepth : null
65+ const depth =
66+ target && target . $vnode && target . $vnode . data
67+ ? target . $vnode . data . routerViewDepth
68+ : null
5169
52- console . log ( 'found depth' , depth )
70+ if ( depth != null ) {
71+ const removeGuard = router . beforeEach ( ( to , from , next ) => {
72+ return fn ( to , from , depth ) ? guard ( to , from , next ) : next ( )
73+ } )
5374
54- // TODO: allow multiple guards?
55- i . proxy . $options . beforeRouteUpdate = guard
75+ onUnmounted ( removeGuard )
76+ return removeGuard
77+ }
5678
57- const removeGuard = router . beforeEach ( ( to , from , next ) => {
58- // TODO: check it's an update
59- return guard ( to , from , next )
60- } )
79+ return noop
80+ }
6181
62- onUnmounted ( removeGuard )
82+ function isUpdateNavigation ( to , from , depth ) {
83+ const toMatched = to . matched
84+ const fromMatched = from . matched
85+ return (
86+ toMatched . length >= depth &&
87+ toMatched
88+ . slice ( 0 , depth + 1 )
89+ . every ( ( record , i ) => record === fromMatched [ i ] )
90+ )
91+ }
6392
64- return removeGuard
93+ function isLeaveNavigation ( to , from , depth ) {
94+ const toMatched = to . matched
95+ const fromMatched = from . matched
96+ return toMatched . length < depth || toMatched [ depth ] !== fromMatched [ depth ]
6597}
6698
67- // TODO:
68- // export function onBeforeRouteLeave () {}
99+ const noop = ( ) => { }
100+
101+ export function onBeforeRouteLeave ( guard ) {
102+ const i = getCurrentInstance ( )
103+ if ( process . env . NODE_ENV !== 'production' && ! i ) {
104+ throwNoCurrentInstance ( 'onBeforeRouteLeave' )
105+ }
106+
107+ return useFilteredGuard ( guard , isLeaveNavigation )
108+ }
69109
70110function throwNoCurrentInstance ( method ) {
71111 throw new Error (
0 commit comments