Vue Router 返回后记住滚动条位置的实现方法

 更新时间:2023年09月07日 10:52:26   作者:悦爱克鲁伊夫  
使用 Vue router 创建 SPA(Single Page App),往往有这种需求:首页是列表页,点击列表项进入详情页,在详情页点击返回首页后,希望看到的是,首页不刷新,并且滚动条停留在之前的位置,这篇文章主要介绍了Vue Router 返回后记住滚动条位置的实现方法,需要的朋友可以参考下

使用 Vue router 创建 SPA(Single Page App),往往有这种需求:首页是列表页,点击列表项进入详情页,在详情页点击返回首页后,希望看到的是,首页不刷新,并且滚动条停留在之前的位置。

使用 Vue router 创建 SPA(Single Page App),往往有这种需求:首页是列表页,点击列表项进入详情页,在详情页点击返回首页后,希望看到的是,首页不刷新,并且滚动条停留在之前的位置。效果如图:

效果

这里涉及两个功能点:

  • route 返回后不刷新页面
  • route 返回后滚动条跳转到离开之前的位置

功能一:route 返回后不刷新页面

该功能比较常用,使用 keep-alive 即可。首先 keep-alive 包裹 router-view ,代码如下:

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

然后,在 router.js 中,对不需要刷新的 route 项 meta.keepAlive 标记为 true,即可实现。代码如下:

export default new Router({
  ...
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home,
      meta: {
        keepAlive: true // 需要缓存
      }
    },
    {
      path: '/about',
      name: 'about',
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
      meta: {
        keepAlive: false // 不需要缓存
      }
    }
  ]
  ...
})

功能二:route 返回后滚动条跳转到离开之前的位置

为了实现该功能,在网上查找,发现 scrollBehavior 出现最多,但经过测试,只能点击浏览器自带的返回按钮才有效,如点击自定义的按钮返回则失败。继续找,发现以下这种方法可以实现,分2步:

  • 获取并存储页面的 scrollTop value
  • 返回页面时取出并设置 scrollTop value

第一步: 获取并存储页面的 scrollTop value

首页组件,点击列表项 route 到详情页之前,先获取存储当前 scrollTop。查看 clickItem 方法,代码如下:

<template>
  <div class="wrapper">
    <ul class="list">
      <li v-for="item in dataList" @click="clickItem(item)">
        {{ item }}
      </li>
    </ul>
  </div>  
</template>
<script>
  export default {
    name: 'simple-scollbehavior',
    data() {
      return {
        dataList: [
          'Start', '(´・ω・`) ', '(/TДT)/ ', '>ㅂ<',
          'o(*≧▽≦)ツ', '(≖ ‿ ≖)✧', '(o^∇^o)ノ', ' (´・ω・)ノ',
          '(´・ω・`)', 'ヽ(・ω・。)ノ', '(`・ω・´)', '╰(*°▽°*)╯',
          '╮( ̄▽ ̄)╭', '( ̄▽ ̄)~*', '(⊙ˍ⊙)', '====',
          '(ง •̀_•́)ง', '(´・ω・`) ', '(/TДT)/ ', '>ㅂ<',
          '╮( ̄▽ ̄)╭', '( ̄▽ ̄)~*', '(⊙ˍ⊙)', 'End'
        ],
        keepScroll: 0 // 记录离开页面时的 scroll-positon 
      };
    },
    methods: {
      clickItem(item){
        const scrollTop = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop)
        this.keepScroll = scrollTop;
        this.$router.push('/about')
      }
    }
  };
</script>

第二步:返回页面时取出并设置 scrollTop value

由于首页设置了 keepAlive,页面不会刷新所以组件内的生命周期方法都不会执行,除了 activated 生命方法。官方说法当组件在 <keep-alive> 内被切换时,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

所以,将设置 scrollTop value 写在 activated 即可。但这里遇到一个坑,直接写无效,必须使用 setTimeOut 延迟执行才有效。具体原因,还有待解惑。代码如下:

<template>
...
</template>
<script>
  export default {
    name: 'simple-scollbehavior',
    ...
    //keep-alive 中组件激活 lifecircle-func
    //注意:必须 setTimeout 才能有效 scrollTop to body
    activated() {
      var gotoScroll = this.keepScroll
      setTimeout(function(){
          //兼容 PC and Mobile 写两个
          document.body.scrollTop = gotoScroll;
          document.documentElement.scrollTop = gotoScroll;
      }, 10);
    }
  };
</script>

完整代码如下:

<template>
  <div class="wrapper">
    <ul class="list">
      <li v-for="item in dataList" @click="clickItem(item)">
        {{ item }}
      </li>
    </ul>
  </div>  
</template>
<script>
  export default {
    name: 'simple-scollbehavior',
    data() {
      return {
        dataList: [
          'Start', '(´・ω・`) ', '(/TДT)/ ', '>ㅂ<',
          'o(*≧▽≦)ツ', '(≖ ‿ ≖)✧', '(o^∇^o)ノ', ' (´・ω・)ノ',
          '(´・ω・`)', 'ヽ(・ω・。)ノ', '(`・ω・´)', '╰(*°▽°*)╯',
          '╮( ̄▽ ̄)╭', '( ̄▽ ̄)~*', '(⊙ˍ⊙)', '====',
          '(ง •̀_•́)ง', '(´・ω・`) ', '(/TДT)/ ', '>ㅂ<',
          '╮( ̄▽ ̄)╭', '( ̄▽ ̄)~*', '(⊙ˍ⊙)', 'End'
        ],
        keepScroll: 0 // 记录离开页面时的 scroll-positon 
      };
    },
    methods: {
      loadmore(loaded) {
        setTimeout(() => {
          this.dataList = this.dataList.concat(this.dataList);
          loaded('done');
        }, 2000);
      },
      clickItem(item){
        const scrollTop = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop)
        this.keepScroll = scrollTop;
        this.$router.push('/about')
      }
    },
    //keep-alive 中组件激活 lifecircle-func
    //注意:必须 setTimeout 才能有效 scrollTop to body
    activated() {
      var gotoScroll = this.keepScroll
      setTimeout(function(){
          //兼容 PC and Mobile 写两个
          document.body.scrollTop = gotoScroll;
          document.documentElement.scrollTop = gotoScroll;
          console.debug('set:' + gotoScroll)
      }, 10);
    }
  };
</script>

到此这篇关于Vue Router 返回后记住滚动条位置的实现方法的文章就介绍到这了,更多相关vue返回记住滚动条位置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue多选列表组件深入详解

    Vue多选列表组件深入详解

    这篇文章主要介绍了Vue多选列表组件深入详解,这个是vue的基本组件,有需要的同学可以研究下
    2021-03-03
  • 浅谈使用Vue完成移动端apk项目

    浅谈使用Vue完成移动端apk项目

    这几天,我做了一个vue移动端的小项目,本文主要介绍了Vue移动端apk项目,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • vue中实现弹出层动画效果的示例代码

    vue中实现弹出层动画效果的示例代码

    这篇文章主要介绍了vue中怎样实现弹出层动画效果,由上而下渐渐显示,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-09-09
  • Vuex中实现数据状态查询与更改

    Vuex中实现数据状态查询与更改

    今天小编就为大家分享一篇Vuex中实现数据状态查询与更改,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue路由事件beforeRouteLeave及组件内定时器的清除方法

    vue路由事件beforeRouteLeave及组件内定时器的清除方法

    今天小编就为大家分享一篇vue路由事件beforeRouteLeave及组件内定时器的清除方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 一文带你理解 Vue 中的生命周期

    一文带你理解 Vue 中的生命周期

    在我们实际项目开发过程中,会非常频繁地和 Vue 组件的生命周期打交道,接下来我们就从源码的角度来看一下这些生命周期的钩子函数是如何被执行的,需要的朋友可以参考下面文章内容
    2021-09-09
  • vue使用input封装上传文件图片全局组件的示例代码

    vue使用input封装上传文件图片全局组件的示例代码

    实际开发过程中,我们经常遇见需要上传文件图片功能,可以封装一个全局组件来调用,这篇文章给大家介绍vue使用input封装上传文件图片全局组件,感兴趣的朋友跟随小编一起看看吧
    2023-11-11
  • npm install安装报错的几种常见情况

    npm install安装报错的几种常见情况

    当你跑起一个项目的时候,第一步需要先安装依赖npm install,下面这篇文章主要给大家介绍了关于npm install安装报错的几种常见情况,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Vue源码之关于vm.$delete()/Vue.use()内部原理详解

    Vue源码之关于vm.$delete()/Vue.use()内部原理详解

    这篇文章主要介绍了Vue源码之关于vm.$delete()/Vue.use()内部原理详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • 基于vue.js无缝滚动效果

    基于vue.js无缝滚动效果

    这篇文章主要介绍了一个基于vue.js无缝滚动效果,文中给大家介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下
    2018-01-01

最新评论