vue使用keep-alive组件缓存,保存页面滚动位置
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
需求:
vue项目H5页面列表页可以向上滑动加载下一页;当点击跳转详情页时,保留列表页的滚动位置;当从详情页点击跳转二级页面时,保存详情页的滚动位置。
思路:
- 列表页的滚动使用的是vux组件库中的Scroller组件,通过观察发现没有滚动条,而是通过样式transform实现的;当跳转详情页的时候缓存列表页可以记录当前位置和数据。
- 详情页页面未使用组件,而是通过原生的div平铺下来的内容,超出屏幕可视区域后自动生成滚动条,当跳转子表单页面的时候缓存详情页的数据及位置,发现此时详情页的数据缓存了,但是滚动条的位置并没有被记录,从子表单返回到详情页的时候,详情页还是回到最顶部。
- 针对详情页滚动条不能被缓存有以下两种思路:一是,在详情页的div最外层加Scroller组件,此时,详情页面的滚动也通过样式控制,就不存在滚动条了;二是,不需要在最外层加Scroller组件,而是在跳转子表单时记录滚动条位置,在切换回来时给scrollTop重新赋值其滚动位置。
代码:
App.vue
<template>
<div id="app">
// 使用keep-alive组件包裹路由
<keep-alive :include="keepAliveList">
<router-view></router-view>
</keep-alive>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'app',
// 获取最新的keepAliveList 绑定给include
computed: {
...mapGetters(['keepAliveList']),
},
data(){
return{}
}
}
</script>
vuex
store/modules/keepAlive.js
const state = {
// 所有需要被缓存页面name组成的数组
keepAliveList: []
}
const mutations = {
// 当pageName不在keepAliveList数组里的时候,就将该pageName存到数组中
SET_KEEP_ALIVE_LIST: (state, pageName) => {
if (!state.keepAliveList.includes(pageName)) {
state.keepAliveList = [...state.keepAliveList, pageName]
}
},
DEL_KEEP_ALIVE_LIST: (state, pageName) => {
// findIndex() 方法为数组中的每个元素都调用一次函数执行:
//当数组中的元素在测试条件时返回 true 时, findIndex() 返回符合条件的元素的索引位置,之后的值不会再调用执行函数。
//如果没有符合条件的元素返回 -1
if (state.keepAliveList.includes(pageName)) {
const index = state.keepAliveList.findIndex(item => item === pageName)
// const index = state.keepAliveList.findIndex(function (item) {
// if (item === pageName) {
// return item
// }
// })
state.keepAliveList.splice(index, 1)
}
}
}
export default {
// commit、dispach的时候在触发的方法前加上该模块名,为了方便找到对应的文件。具体如下
// this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', this.$options.name)
// 如果namespaced: true,具体页面则可以按照上面
namespaced: true,
state,
mutations
}
store/modules/keepAliveGetters.js
// 相当于计算属性
// 当keepAliveList,变化时,它会重新求值并且把结果缓存起来;如果没有变化,它会用之前缓存好的值
const getters = {
keepAliveList: state => state.keepAlive.keepAliveList
// keepAliveList: function(state) {
// return state.keepAlive.keepAliveList
// }
};
export default getters
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import global from './global/'
//引入
import keepAlive from './modules/keepAlive.js'
import keepAliveGetters from './modules/keepAliveGetters'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
global,
keepAlive
},
// 导出
getters: keepAliveGetters
})
projList.vue
<template>
// 使用滚动组件
<scroller v-if="listView" lock-x class="scrollerBox" @on-scroll-bottom="onScrollBottom" ref="scrollerBottom" :scroll-bottom-offst="0" style="padding-bottom:0;">
<div class="box">
</div>
</scroller>
</template>
<script>
export default {
// 首先name唯一,keepAlive的是需要用到 / 递归组件的时候需要用到
name: 'projList',
data(){
return{
listView: true,
}
},
// 通过这种方式,我们在导航转入新的路由前获取数据
// beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。通过 `vm` 访问组件实例
beforeRouteEnter(to, from, next) {
next(vm => {
vm.$store.commit('keepAlive/SET_KEEP_ALIVE_LIST', vm.$options.name)
})
},
beforeRouteLeave(to, from, next) {
if (to.path !== '/project/detail') {
this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', this.$options.name)
}
next()
},
created () {},
methods: {}
}
</script>
projDetail.vue
<template>
<scroller lock-x style="padding-bottom:0;">
<div>
</div>
</scroller>
</template>
export default {
name: 'projDetail',
data () {
return {}
},
created () {},
// 进入这个页面之前
beforeRouteEnter(to, from, next) {
next(vm => {
vm.$store.commit('keepAlive/SET_KEEP_ALIVE_LIST', vm.$options.name)
})
},
// 离开这个页面之前
beforeRouteLeave(to, from, next) {
const keys = ['/project/pay', '/project/contract', '/project/payment']
if (!keys.includes(to.path)) {
this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', this.$options.name)
}
next()
},
}
参考文章:
vue 使用keep-alive缓存tab切换组件,保持每个组件滚动条位置
路由导航守卫beforeRouteEnter / beforeRouteLeave
keep-alive
在动态组件上使用 keep-alive
JavaScript findIndex() 方法
JavaScript splice() 方法
GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
更多推荐
已为社区贡献1条内容
所有评论(0)