I'm building web app with Vue and have some strange behavior on iOS (Safari).
When route changes Safari won't scroll to top of the page (everything's fine on other platforms/browsers)
Has someone faced such problems?
Thanks.
The router doesn't automatically scroll to top when the route changes. You can do that in a global before hook though:
router.beforeEach(function (transition) {
window.scrollTo(0, 0)
transition.next()
})
Any elegant way to solve this problem?
Solution @yyx990803 proposed is pretty elegant... Why you don't like it?
Just first impression, I think it's OK now 😀
Thanks for your post.
thanks! @yyx990803, i also have this problem.
Is this available in vue-router@next?
I managed to use this per component
export default{
data(){
return {}
},
created() {
//Scrolls to top when view is displayed
window.scrollTo(0, 0);
}
}
But wondering if it is a router configuration
@asantibanez Checkout scrollBehavior https://github.com/vuejs/vue-router/releases
Looks like the arguments for beforeEach are now to, from, next instead of just transition.
https://router.vuejs.org/en/advanced/navigation-guards.html#global-guards
@yyx990803's example would now be:
router.beforeEach(function (to, from, next) {
window.scrollTo(0, 0)
next();
})
Setting global scrollBehavior to the router works fine for me, but is there any elegant solution to animate the scrolling of the window within vue-router. I can set my animation in router.beforeEach function, but was just wondering...
@panayotov
Use this
scrollToTop: function (scrollDuration) {
var cosParameter = window.scrollY / 2,
scrollCount = 0,
oldTimestamp = performance.now();
function step(newTimestamp) {
scrollCount += Math.PI / (scrollDuration / (newTimestamp - oldTimestamp));
if (scrollCount >= Math.PI) window.scrollTo(0, 0);
if (window.scrollY === 0) return;
window.scrollTo(0, Math.round(cosParameter + cosParameter * Math.cos(scrollCount)));
oldTimestamp = newTimestamp;
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
}
https://stackoverflow.com/questions/21474678/scrolltop-animation-without-jquery
The fix would scroll current page to top then do the route. That's not what people want if they have route animation.
@pajtai - Stupid question here. Where do I add that customization? I have a webpack application with my main.js as :
```import Vue from 'vue'
import Vuetify from 'vuetify'
import App from './App'
import router from './router'
Vue.use(Vuetify)
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
render: h => h(App)
})
``
I tried inserting into my main.js before thenew Vue` bit, but it didn't work.
Just wanted to piggyback @jesong's comment and (re?)highlight this problem. Using beforeEach to scroll causes the page to scroll before any route animation is made, which doesn't look too good.
For those that want to apply the animation after the route has changed, or doesn't want that odd flicker of the view when using the scrollTop in a beforeEach. You are always welcome to use the afterEach hook provided by the router.
router.afterEach(() => {
window.scrollTo(0, 0);
});
Reference: https://router.vuejs.org/en/api/router-instance.html
This is better (scrollBehavior):
export default new Router({
scrollBehavior() {
return { x: 0, y: 0 };
},
routes: [
{
path: '/',
name: 'Home',
component: Home
}
],
mode: 'history'
});
See https://router.vuejs.org/guide/advanced/scroll-behavior.html#async-scrolling
@yyx990803 thanks it worked for me.
@edarioq
I had an ugly jump to the top of the current page before leaving.
I put the window.scrollTo(x, y) in the beforeCreate() hook and it worked
This is better (scrollBehavior):
export default new Router({ scrollBehavior() { return { x: 0, y: 0 }; }, routes: [ { path: '/', name: 'Home', component: Home } ], mode: 'history' });See https://router.vuejs.org/guide/advanced/scroll-behavior.html#async-scrolling
Thank you for the solution. This is working for my project.
Most helpful comment
The router doesn't automatically scroll to top when the route changes. You can do that in a global before hook though: