SPA页面是多组件拼起来的,这时候就存在组件之间的切换问题,Vue中也提出了动态组件的概念,使得我们可以更好的实现组件之间的切换效果 , 但是vue中组件的切换实际是组件本身重新创建和销毁的过程,在某些场景下我们并不希望组件被重新创建重新渲染
这里我就主要介绍Vue中组件的切换以及缓存解决方法
一、组件的切换方式
(1) 使用 v-if和v-else或者(v-show)
<Com1 v-if="istrue" />
<Com2 v-else />
当里面的istrue为true 时,Com1 显示,否则就是Com2 进行显示
(2) 使用is特性来进行动态组件的切换
<template>
<div>
<a href="#" @click.prevent="comName = 'login'">登录</a>
<a href="#" @click.prevent="comName = 'register'">注册</a>
<a href="#" @click.prevent="comName = 'logOut'">退出</a>
<component :is="comName"></component>
</div>
</template>
(3) 使用路由(router)进行动态组件的切换
{
path: '/login',
name: 'login',
component: () => import('../views/login.vue')
},
{
path: '/register',
name: 'register',
component: () => import('../views/register.vue')
},
<router-view />
二、组件缓存
组件的缓存可以在进行动态组件切换的时候对组件内部数据进行缓存,而不是走销毁流程
使用场景: 多表单切换,对表单内数据进行保存
1.keep-alive定义:
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。 当组件在<keep-alive> 内被切换,它的activated 和 deactivated 这两个生命周期钩子函数将会被对应执行 。
2.keep-alive的两个钩子函数
activated | deactivated |
---|
在 keep-alive 组件激活时调用 | 在keep-alive 组件停用时调用 | 该钩子函数在服务器端渲染期间不被调用 | 该钩子在服务器端渲染期间不被调用 |
使用keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来created 钩子函数中获取数据的任务。
注意: 只有组件被keep-alive 包裹时,这两个生命周期函数才会被调用,如果作为正常组件使用,是不会被调用的
在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子函数依然不会被调用!在服务端渲染时,此钩子函数也不会被调用。
设置了缓存的组件钩子调用情况:
第一次进入:beforeRouterEnter ->created->…->activated->…->deactivated> beforeRouteLeave
后续进入时:beforeRouterEnter ->activated->deactivated> beforeRouteLeave
3.keep-alive使用方法
(1)Props
include - 字符串 || 数组 || 正则 名称匹配的组件会被缓存-->include的值为组件的name。
exclude - 字符串 || 正则 任何名称匹配的组件都不会被缓存。
max - 数量 决定最多可以缓存多少组件。
(2)搭配<component></component> 使用
<template>
<div>
<a href="#" @click.prevent="comName = 'login'">登录</a>
<a href="#" @click.prevent="comName = 'register'">注册</a>
<a href="#" @click.prevent="comName = 'logOut'">退出</a>
<keep-alive include="login">
<component :is="comName"></component>
</keep-alive>
</div>
</template>
(3)搭配路由使用
需配置路由meta信息的keepAlive 属性 keep-alive 代码可以结合v-if进行包裹,如果meta中的keepAlive 为true进行缓存,否则不进行缓存,这样可以更灵活
{
path: '/login',
name: 'login',
component: () => import('../page/login.vue')
meta:{
keepAlive : true
}
},
{
path: '/index',
name: 'index',
component: () => import('../page/index.vue'),
meta:{
keepAlive : false
}
}
<div id="app">
<keep-alive>
<!-- 需要缓存的视图组件 -->
<router-view v-if="$route.meta.keepAlive"> </router-view>
</keep-alive>
<!-- 不需要缓存的视图组件 -->
<router-view v-if="!$route.meta.keepAlive"> </router-view>
</div>
(4)清除缓存组件
beforeRouteLeave(to, from, next) {
if (to.path === "/goods_detail") {
from.meta.keepAlive = true;
} else {
from.meta.keepAlive = false;
}
next();
}
拓展:
beforeRouteLeave 钩子
beforeRouteLeave(to, from, next) : 离开路由之前执行的函数,可用于页面的反向传值,页面跳转。
beforeRouteLeave (to, from, next) {
if (to.name === 'home') {
to.query.temp = '选中后的地址'
}
console.log(to)
console.log(from)
next()
},
|