时间:2021-05-25
引入
在使用vue + vue-router开发SPA的时候,有没有遇到过这样的情况:当我们在列表页和详情页之间切换的时候,如果列表页不做缓存,会导致每次从详情页返回时,列表页都会重新加载。如下图:
细心的朋友已经发现了,当从详情页返回列表页的时候,列表页重载了,这样的体验显然不好,这时我们可以对列表页进行缓存处理。
keep-alive实现页面缓存
我们的项目不一定所有页面都需要做缓存处理,所以这里介绍两种按需缓存的方法:
方法一:
首先在定义路由的时候配置 meta 字段,自定义一个KeepAlive字段作为该页面是否缓存的标记:
routes:[{ path: '/search', name: 'search', component: search, meta: { title: '搜索列表页', keepAlive: true // 标记列表页需要被缓存 }},{ path: '/detail', name: 'detail', component: detail, meta: { title: '详情页', // 详情页不需要做缓存,所以不加keepAlive标记 }}]由于<keep-alive>组件不支持v-if指令,所以我们在App.vue中采用两个<router-view>的写法,通过当前路由的keepAlive字段来判断是否对页面进行缓存:
<div id="app"> <keep-alive> <router-view v-if="$route.meta.keepAlive" /> </keep-alive> <router-view v-if="!$route.meta.keepAlive" /></div>方法二
使用<keep-alive>提供的 exclude 或者 include 选项,此处我们使用 exclude ,在App.vue中:
<div id="app"> <keep-alive exclude="detail"> <router-view /> </keep-alive></div>需要注意的是,一定要给页面组件加上相应的name,例如在detail.vue中:
<script>export default { name: 'detail', // 这个name要和keep-alive中的exclude选项值一致 ...}</script>这么写就代表了在项目中除了name为detail的页面组件外,其余页面都将进行缓存。
特殊情况优化:
如果详情页也做了keep-alive,那么列表页和详情页切换时,滚动位置可能会相互影响,这时需要在 Router 实例中提供一个 scrollBehavior 方法:
export default new Router({ scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } }, routes: [...],})效果展示
效果看似很不错,实现了列表页的缓存。但这其实并不灵活,比如返回首页再进入这个搜索页的时候,由于没做任何处理,所以这个搜索页它仍处于之前的状态:
然而,我希望凡是从首页进入搜索页,页面数据都需要重置回初始状态,有没有什么方可以灵活控制页面数据是否需要重置呢?这时我的脑海里浮现了vue生态系统中的状态管理库vuex。
借助vuex使页面更灵活
需求分析: 我们需要一个全局的flag来控制每次进入缓存页时,数据是否需要重置,正好vuex能做到。
vuex搞起来
安装
npm install vuex --save
配置vuex
为了方便日后维护,可以创建一个store目录专门存放vuex的模块代码,目录结构参考下图:
state.js:
const state = { refreshSearch: true // 标记是否刷新搜索页}export default statemutation.js
const matutaions = { setRefreshSearch(state, flag) { state.refreshSearch = flag }} export default matutaionsindex.js
import Vue from 'vue'import Vuex from 'vuex'import state from './state'import mutations from './mutations'Vue.use(Vuex)export default new Vuex.Store({ state, mutations})在入口文件main.js中:
import store from './store' //这里是指向store目录中的index.jsnew Vue({ router, store, render: h => h(App)}).$mount('#app')这样,我们就相当于用vuex创建了一个用来判断页面是否需要重置的标记了。
为所欲为地重置你的缓存页中的数据
在哪里重置
keep-alive的组件有个特有的生命周期钩子activated()。activated()会在keep-alive的组件每次激活时调用,而created()只有创建的时候会被调用一次,再次激活就不会被调用了。所以这里我们需要在activated()钩子中重置我们的页面数据。
在activated()中想重置就重置
这里要借助vuex中的refreshSearch标记来判断是否需要重置
search.vue:(这个是需要缓存的页面)
<script>import {mapState, mapMutations} from 'vuex' //vuex提供的映射函数,用来简化代码的export default { activated() { if (this.refreshSearch) { // 若为true,则执行重置页面等相关操作 this.fetchData(); } else { this.reset(true); } }, methods:{ fetchData() { // 获取页面数据 }, ...mapMutations({ reset: 'setRefreshSearch' // 将 `this.reset()` 映射为 `this.$store.commit('setRefreshSearch')` }) }, computed: { ...mapState([ 'refreshSearch' // 映射 this.refreshSearch 为 this.$store.state.refreshSearch ]), }}</script>当我们从搜索页去详情页时,希望搜索页缓存,只需要把标记设为false:
methods: { goDetail() { this.reset(false) // 这样返回搜索页的时候,搜索页就不会重置数据了 this.$router.push({path: '/detail'}) }, ...mapMutations({ reset: 'setRefreshSearch' })}当我们从首页去搜索页时,希望搜索页数据重置,只需把标记设为true:
methods: { goSearch() { this.reset(true) // 这样去搜索页时数据就会被重置了 this.$router.push({path: '/search'}) }, ...mapMutations({ reset: 'setRefreshSearch' })}效果预览
总结
本文介绍了按需使用keep-alive,以及借助vuex来控制keep-alive的组件页面的数据是否需要重置刷新,希望对大家有帮助。
附送相关知识传送门:
vue内置组件keep-alive
vue-router滚动行为
生命周期钩子activated
vuex状态管理库
以上所述是小编给大家介绍的keep-alive + vuex 让缓存的页面灵活起来详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
版权1、外层包围keep-alive作用将组件实例缓存下来2、清除组件缓存使用keep-alive的exclude="组件名"属性补充知识:vue简单的页面刷新
Vue工程中有些页面需要有缓存。这个功能通过keep-alive组件实现,keep-alive组件可以使被包含的组件保留状态,或避免重新渲染。 在rout
Vue中keep-alive的使用我总结的有两种方式应用:首先简述一下keep-alive的作用,kee-alive可以缓存不活动的的组件。当组件之间进行相互切
实现全站的页面缓存,前进刷新,返回走缓存,并且能记住上一页的滚动位置,参考了很多技术实现,github上的导航组件实现的原理要么使用的keep-alive,要么
vue2.0keep-alive的最佳实践,供大家参考,具体内容如下1.基本用法vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组