Skip to content

Commit c93a734

Browse files
homerjamyyx990803
authored andcommitted
feat: call scrollBehavior with app context (#1804)
* Call scrollBehavior with app context This allows us to listen for events in the scroll behavior hook, thus enabling us to resolve a promise returned by the hook upon triggering of some custom event (for example one emited on the $root by an after-leave transition event). * Update scrollBehavior example * change scrollBehavior context to router
1 parent 8ee872f commit c93a734

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

examples/scroll-behavior/app.js

+29-19
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,41 @@ const scrollBehavior = function (to, from, savedPosition) {
2525
// savedPosition is only available for popstate navigations.
2626
return savedPosition
2727
} else {
28-
return new Promise(resolve => {
29-
const position = {}
30-
let delay = 500
31-
// new navigation.
32-
// scroll to anchor by returning the selector
33-
if (to.hash) {
34-
position.selector = to.hash
28+
const position = {}
29+
30+
// scroll to anchor by returning the selector
31+
if (to.hash) {
32+
position.selector = to.hash
3533

36-
// specify offset of the element
37-
if (to.hash === '#anchor2') {
38-
position.offset = { y: 100 }
39-
}
34+
// specify offset of the element
35+
if (to.hash === '#anchor2') {
36+
position.offset = { y: 100 }
37+
}
4038

41-
if (document.querySelector(to.hash)) {
42-
delay = 0
43-
}
39+
if (document.querySelector(to.hash)) {
40+
return position
4441
}
42+
43+
// if the returned position is falsy or an empty object,
44+
// will retain current scroll position.
45+
return false
46+
}
47+
48+
return new Promise(resolve => {
4549
// check if any matched route config has meta that requires scrolling to top
4650
if (to.matched.some(m => m.meta.scrollToTop)) {
4751
// coords will be used if no selector is provided,
4852
// or if the selector didn't match any element.
4953
position.x = 0
5054
position.y = 0
5155
}
56+
5257
// wait for the out transition to complete (if necessary)
53-
setTimeout(() => {
54-
// if the returned position is falsy or an empty object,
58+
this.app.$root.$once('triggerScroll', () => {
59+
// if the resolved position is falsy or an empty object,
5560
// will retain current scroll position.
5661
resolve(position)
57-
}, delay)
62+
})
5863
})
5964
}
6065
}
@@ -82,9 +87,14 @@ new Vue({
8287
<li><router-link to="/bar#anchor">/bar#anchor</router-link></li>
8388
<li><router-link to="/bar#anchor2">/bar#anchor2</router-link></li>
8489
</ul>
85-
<transition name="fade" mode="out-in">
90+
<transition name="fade" mode="out-in" @after-leave="afterLeave">
8691
<router-view class="view"></router-view>
8792
</transition>
8893
</div>
89-
`
94+
`,
95+
methods: {
96+
afterLeave () {
97+
this.$root.$emit('triggerScroll')
98+
}
99+
}
90100
}).$mount('#app')

src/util/scroll.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function handleScroll (
3939
// wait until re-render finishes before scrolling
4040
router.app.$nextTick(() => {
4141
const position = getScrollPosition()
42-
const shouldScroll = behavior(to, from, isPop ? position : null)
42+
const shouldScroll = behavior.call(router, to, from, isPop ? position : null)
4343

4444
if (!shouldScroll) {
4545
return

0 commit comments

Comments
 (0)