用vue做单页应用,在我们来回切换路由或者点击返回键的时候,页面总是会重新刷新。这样的用户体验是非常差的,我们希望页面的数据会保留,而不是每次进入都要重新载入。这里我们可以使用vue官方提供的内置组件keep-alive,------>官方传送门。下面简单介绍一下如何使用。
1、所有的组件都缓存
<keep-alive>
<router-view></router-view>
</keep-alive>
在router-view外层包裹keep-alive,这样页面均只载入一次,当然这是不可取的,也不常用。
2、指定组件缓存
keep-alive提供include参数
字符串或正则表达式。只有名称匹配的组件会被缓存。
示例
<keep-alive include="name">
<router-view></router-view>
</keep-alive>
只缓存name
<keep-alive include="name,index">
<router-view></router-view>
</keep-alive>
只缓存name,index
所谓动态缓存,即我们要根据来自哪个页面来判断当前是否更新。这里就需要给keep-alive一个参数,用于判断。
下面示例有三个页面,home ,about,news。
需求如下:
- home和about可以来回切换,其中about被缓存,而home每次从about进入都会更新
- home页面可以进入list,每次进入list都会刷新,而从list返回home,home不刷新
大致思路如下:
第一步:首先给keepAlive组件一个值keepAlive,第一步在App.vue配置
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 被缓存,比如about -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
<!-- 被刷新,比如home -->
当keepAlive的值为true,则缓存,为false则更新
第二步:
在router配置文件,index.js配置keepAlive参数:
{
path: '/',
name: 'home',
component: Home,
meta:{
app:true, //这个是为了在news页面隐藏App.vue的导航栏,此处忽略
keepAlive:true //默认home缓存
}
},
{
path: '/about',
name: 'about',
component: About,
meta:{
app:true,
keepAlive:true //默认about缓存
}
},
{
path: '/news',
name: 'news',
component: News,
meta:{
app:false,
keepAlive:false //默认news更新
}
},
这样about和home页面只更新一次,而news每次都更新
第三步:
接下来就考虑从不同的页面进入home,来决定home是否缓存。所以我们需要根据进home页面的路由来改变keepAlive的值。
1、在home.vue添加导航守卫beforeRouteLeave
beforeRouteLeave(to, from, next) {
from.meta.keepAlive = false;
next();
},
当从home页面离开即触发这段代码
因为默认home为缓存,所以每次离开时将home修改为更新,此时每次从about进入home都会更新
2、在news.vue添加导航守卫beforeRouteLeave
beforeRouteLeave(to, from, next) {
if (to.path == "/") {
to.meta.keepAlive = true;
} else {
to.meta.keepAlive = false;
}
next();
},
当从news页面离开即触发,
如果news进入的是home页面,则将home页面的keepAlive 改为true即缓存,否则改为false。
这样所有的配置已经完成,可以实现上面所说的需求
为了更直观的展现效果,我们在每个页面创建时打印一段话,例如home页面
created() {
console.log('home刷新了')
},
<template>
<div id="app">
<div id="nav" v-show="$route.meta.app">
<router-link to="/">Homerouter-link> |
<router-link to="/about">Aboutrouter-link>
div>
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
router-view>
keep-alive>
<router-view v-if="!$route.meta.keepAlive">router-view>
div>
template>
index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import News from '../views/News.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: Home,
meta:{
app:true,
keepAlive:true
}
},
{
path: '/about',
name: 'about',
component: About,
meta:{
app:true,
keepAlive:true
}
},
{
path: '/news',
name: 'news',
component: News,
meta:{
app:false,
keepAlive:false
}
},
]
const router = new VueRouter({
// mode: 'hash',
base: process.env.BASE_URL,
routes
})
export default router
Home.vue
<template>
<div class="home">
<p>主页p>
<h2> <router-link to="/news">点击进入新闻页router-link>h2>
div>
template>
<script>
export default {
name: 'home'
beforeRouteLeave(to, from, next) {
from.meta.keepAlive = false;
next();
},
created() {
console.log('home刷新了')
},
}
script>
About.vue
<template>
<div class="about">
这是关于页面
div>
template>
<script>
export default{
name: 'about',
mounted() {
console.log('about刷新了')
}
}
script>
News.vue
<template>
<div class="main">
<h1>这里是新闻页h1>
div>
template>
<script>
export default{
name: 'news',
beforeRouteLeave(to, from, next) {
if (to.path == "/") {
to.meta.keepAlive = true;
} else {
to.meta.keepAlive = false;
}
next();
},
created() {
console.log('news刷新了')
},
}
script>
<style>
style>