Skip to content

Commit

Permalink
feat: call scrollBehavior with app context (#1804)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
homerjam authored and yyx990803 committed Oct 23, 2017
1 parent 8ee872f commit c93a734
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 20 deletions.
48 changes: 29 additions & 19 deletions examples/scroll-behavior/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,41 @@ const scrollBehavior = function (to, from, savedPosition) {
// savedPosition is only available for popstate navigations.
return savedPosition
} else {
return new Promise(resolve => {
const position = {}
let delay = 500
// new navigation.
// scroll to anchor by returning the selector
if (to.hash) {
position.selector = to.hash
const position = {}

// scroll to anchor by returning the selector
if (to.hash) {
position.selector = to.hash

// specify offset of the element
if (to.hash === '#anchor2') {
position.offset = { y: 100 }
}
// specify offset of the element
if (to.hash === '#anchor2') {
position.offset = { y: 100 }
}

if (document.querySelector(to.hash)) {
delay = 0
}
if (document.querySelector(to.hash)) {
return position
}

// if the returned position is falsy or an empty object,
// will retain current scroll position.
return false
}

return new Promise(resolve => {
// check if any matched route config has meta that requires scrolling to top
if (to.matched.some(m => m.meta.scrollToTop)) {
// coords will be used if no selector is provided,
// or if the selector didn't match any element.
position.x = 0
position.y = 0
}

// wait for the out transition to complete (if necessary)
setTimeout(() => {
// if the returned position is falsy or an empty object,
this.app.$root.$once('triggerScroll', () => {
// if the resolved position is falsy or an empty object,
// will retain current scroll position.
resolve(position)
}, delay)
})
})
}
}
Expand Down Expand Up @@ -82,9 +87,14 @@ new Vue({
<li><router-link to="/bar#anchor">/bar#anchor</router-link></li>
<li><router-link to="/bar#anchor2">/bar#anchor2</router-link></li>
</ul>
<transition name="fade" mode="out-in">
<transition name="fade" mode="out-in" @after-leave="afterLeave">
<router-view class="view"></router-view>
</transition>
</div>
`
`,
methods: {
afterLeave () {
this.$root.$emit('triggerScroll')
}
}
}).$mount('#app')
2 changes: 1 addition & 1 deletion src/util/scroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function handleScroll (
// wait until re-render finishes before scrolling
router.app.$nextTick(() => {
const position = getScrollPosition()
const shouldScroll = behavior(to, from, isPop ? position : null)
const shouldScroll = behavior.call(router, to, from, isPop ? position : null)

if (!shouldScroll) {
return
Expand Down

0 comments on commit c93a734

Please sign in to comment.