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返回记住滚动条位置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!