vue-router scrollBehavior不起作用

试了官方示例中的scrollBehavior是可以在后退时回到之前的滚动的位置的,但是在我自己的项目中,savedPosition可以打印出之前的位置,但是都是回到顶部,不会回到之前的位置。
经过测试发现是因为页面有网络请求,去掉网络请求就正常了。
于是就想用keep-alive,这样是可以在后退时停留在之前位置了,但是进入下一个页面时也会停留在之前的位置,而且这样所有组件都被缓存了,不卸载掉整个页面就不会重新请求。
所以有什么办法能在后退时停留在之前的滚动位置吗?

阅读 18.8k
7 个回答

导致页面返回时没有滚动到离开时的位置是因为页面是内容是通过网络请求之后再渲染的。
可以通过setTimeout来滚动到页面离开时的位置


scrollBehavior (to, from, savedPosition) {
    if(savedPosition) {
        setTimeout(() => {
            window.scrollTo(savedPosition.x, savedPosition.y)
        }, 200)
    }
}

或者结合keep-alive来达到后退时不刷新数据,前进时刷新数据的效果。

new VueRouter({
    mode: 'history',
    routes: [{
        path: '/foo',    
        component: (resolve) => {
            require(['views/foo'], resolve)
        },
        meta: {isKeepAlive: true}
    }],
    scrollBehavior (to, from, savedPosition) {
        if (savedPosition || typeof savedPosition == 'undefined') { //从第二页返回首页时savePosition为undefined
            //只处理设置了路由元信息的组件
            from.meta.isKeepAlive = typeof from.meta.isKeepAlive == 'undefined' ? undefined : false;
            to.meta.isKeepAlive = typeof to.meta.isKeepAlive == 'undefined' ? undefined : true;
            if(savedPosition) {
                return savedPosition;
            }
        } else {
            from.meta.isKeepAlive = typeof from.meta.isKeepAlive == 'undefined' ? undefined : true;
            to.meta.isKeepAlive = typeof to.meta.isKeepAlive == 'undefined' ? undefined : false;
        }
    }
})


<keep-alive>
    <router-view v-if="$route.meta.isKeepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.isKeepAlive"></router-view>

官方已经不在支持了。

可以通过vuex进行位置的管理

你用的是vue1.x么?我这两天也遇到这个问题了,我设置了savedPosition:true 但是不起作用,于是我用了keep-alive,从详情页返回列表页的时候会记录滚动条的位置,但是,从列表页进入另一个详情页的时候详情页不会边,还是进入的上一个详情页的页面。后来的解决办法是将请求数据的函数写在attached钩子里面就解决了这个问题。

如果你的页面是单页应用,Vuet可以实现你的需求

import Vue from 'vue'
import Vuet from 'vuet'
Vue.use(Vuet)

const vuet = new Vuet({
  modules: {
    testModule: {
      data () {
        return {}
      }
    }
  }
})


new Vue({
  // ...
  vuet,
  template: `
    <div v-vuet-scroll.self="{ path: 'testModule',  name: '随便给一个名字' }"></div>
  `
})

如果你需要记录多个滚动条,调用多次v-vuet-scroll这个指令,设置不同的名字即可

新手上路,请多包涵

对于vue3, savedPosition的对象为{left: xx, top: xx}, 因此代码应该写成:


 setTimeout(() => {
        console.log('croll ', savedPosition)
        window.scrollTo(savedPosition.left, savedPosition.top)
      }, 200)
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题