使用vue-router如何记录滚动条的位置

路由是通过keep-alive transition包裹的

<transition>
    <keep-alive>
        <router-view><router-view>
    </keep-alive>
</transition>

在hash模式下,想让页面返回时回到之前的位置。
思路:页面离开时,保存页面的位置,回到页面时,设置为保存的值。
实现:

// 主要通过afterEach钩子
router.afterEach((to, from) => {
  // 将位置保存在vuex中
  store.commit(type.SAVE_POSITION, {
    name: from.path,
    position: document.body.scrollTop || document.documentElement.scrollTop
  })
  // 设置保存的位置
  if (store.state.positions[to.path]) {
    setTimeout(() => {
      window.scrollTo(0, store.state.positions[to.path])
    }, 80)
  } else {
    setTimeout(() => {
      window.scrollTo(0, 0)
    }, 80)
  }
})

但是这种实现方法却需要通过定时器(我觉得应该是因为afterEach触发时页面还没有挂载到页面),但定时器有不一定准确,又尝试将设置保存位置放到activated钩子中。

...
router.afterEach((to, from) => {
  // 将位置保存在vuex中
  store.commit(type.SAVE_POSITION, {
    name: from.path,
    position: document.body.scrollTop || document.documentElement.scrollTop
  })
}
...

...
// 设置保存的位置
activated () {
  if (this.$store.state.positions[this.$route.path]) {
      window.scrollTo(0, this.$store.state.positions[this.$route.path])
  } else {
      window.scrollTo(0, 0)
  }
})

结果发现实现不了,后来把transition标签去了才可以了,但过渡效果就失效了。

问题

请问有什么好的办法解决?


问题更新

  data () {
    return {
      scrollTop: 0
    }
  },
  deactivated () {
    this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop
  },
  activated () {

    // 保存在data和保存在vuex的数据相等
    console.log(this.scrollTop == this.$store.state.positions[this.$route.path])
    
    // 可以返回到保存的位置上
    window.scrollTo(0, this.scrollTop)
    
    // 不能返回到保存的位置上
    // if (this.$store.state.positions[this.$route.path]) {
    //   window.scrollTo(0, this.$store.state.positions[this.$route.path])
    // }
  }

现两种情况:
一、如果我把页面离开时的数据保存在data中,页面返回时触发activated,执行 window.scrollTo(0, this.scrollTop)可以滚回到保存的位置。
二、如果数据保存在vuex中,页面返回时触发activated,执行window.scrollTo(0, this.$store.state.positions[this.$route.path])却不起作用。

console.log(this.scrollTop == this.$store.state.positions[this.$route.path])打印出来的值是相等的,但出现上面两种情况,有点不太明白了。

求助!

阅读 6.2k
2 个回答

没看到只用hash,让后台配history也是很方便的

--- 按道理是没问题的如果数据没问题, 你看看是不是全等的?
scrollTo(0,200) 可以生效
scrollTo(0,'200') 不生效

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题