解析keepalive和transition如何在Vue3项目里使用
keepalive是什么
keep-alive是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
keepailve的基本用法
- 动态组件中的应用,在线地址:官网的例子
<script setup>
import { shallowRef } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'
// 进行浅层代理,避免不必要的花销
const current = shallowRef(CompA)
</script>
<template>
<div class="demo">
<!--切换时,current.value值会发生改变 -->
<label><input type="radio" v-model="current" :value="CompA" /> A</label>
<label><input type="radio" v-model="current" :value="CompB" /> B</label>
<KeepAlive>
<component :is="current"></component>
</KeepAlive>
</div>
</template>
- 在vue-router中的应用
<keep-alive :include="whiteList" :exclude="blackList" :max="amount">
<router-view></router-view>
</keep-alive>
include
定义缓存白名单,keep-alive会缓存命中的组件;exclude
定义缓存黑名单,被命中的组件将不会被缓存,优先级高于前者;max
定义缓存组件上限,超出上限使用LRU的策略置换缓存数据。
// 只缓存组件name为a或者b的组件
<keep-alive include="a,b">
<component />
</keep-alive>
// 组件name为c的组件不缓存(可以保留它的状态或避免重新渲染)
<keep-alive exclude="c">
<component />
</keep-alive>
// 如果同时使用include,exclude,那么exclude优先于include, 下面的例子只缓存a组件
<keep-alive include="a,b" exclude="b">
<component />
</keep-alive>
// 如果缓存的组件超过了max设定的值5,那么将删除第一个缓存的组件
<keep-alive exclude="c" max="5">
<component />
</keep-alive>
配合router
的高级使用
router-view
也是一个组件,如果直接被包在keepalive
里面,那么所有路径匹配到的视图组件都会被缓存,如下:
<keep-alive>
<router-view>
<!-- 所有路径匹配到的视图组件都会被缓存! -->
</router-view>
</keep-alive>
如果只想要router-view
里面的某个组件被缓存,怎么办?
- 使用
include/exclude
- 使用
meta
属性
1.使用 include
(exclude
例子类似)
//只有路径匹配到的 name 为 a 组件会被缓存
<keep-alive include="a">
<router-view></router-view>
</keep-alive>
2.使用 meta
属性
// routes 配置
export default [
{
path: '/',
name: 'home',
component: Home,
meta: {
keepAlive: true // 需要被缓存
}
}, {
path: '/profile',
name: 'profile',
component: Profile,
meta: {
keepAlive: false // 不需要被缓存
}
}
]
<keep-alive>
<router-view v-if="$route.meta.keepAlive">
<!-- 这里是会被缓存的视图组件,比如 Home! -->
</router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive">
<!-- 这里是不会被缓存的视图组件,比如 Profile! -->
</router-view>
配合vue-router
和transition
的高级使用
// App.vue
<script setup>
import { reactive } from 'vue';
const state = reactive({
transitionName: 'slide-left'
})
const router = useRouter()
router.beforeEach((to, from, next) => {
if (to.meta.index > from.meta.index) {
// 从主页面 去到子页面
state.transitionName = 'slide-left'
} else if (to.meta.index < from.meta.index) {
// 子页面回到主页面
state.transitionName = 'slide-right'
} else {
// 平级
state.transitionName = ''
}
})
</script>
<template>
<!-- 渲染路由视图 -->
<router-view v-slot="{ Component }">
<!-- 过渡效果 -->
<transition :name="state.transitionName">
<!-- 缓存组件 -->
<keep-alive>
<component :is='Component' :key="$route.name" v-if="$route.meta.keepAlive" />
</keep-alive>
</transition>
</router-view>
<!-- 渲染路由视图 -->
<router-view v-slot="{ Component }">
<!-- 过渡效果 -->
<transition :name="state.transitionName">
<!-- 不缓存组件 -->
<component :is='Component' :key="$route.name" v-if="!$route.meta.keepAlive" />
</transition>
</router-view>
</template>
<style lang="stylus">
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active
height 100%
/* 提前告知浏览器, 即将会有transform 渐变 */
will-change transform
transition all 600ms
position absolute
backface-visibility hidden
.slide-right-enter-from
opacity 0
transform translate3d(-100%, 0, 0)
.slide-right-leave-active
opacity 0
transform translate3d(100%, 0, 0)
.slide-left-enter-from
opacity 0
transform translate3d(100%, 0, 0)
.slide-left-leave-active
opacity 0
transform translate3d(-100%, 0, 0)
</style>
// router.js
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/views/Home/index.vue'
const routes = [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
name: 'home',
component: Home,
meta: {
keepAlive: true,
index: 1
},
},
{
path: '/detail/:id',
name:'detail',
meta: {
index: 3
},
component: () => import('@/views/Detial/index.vue')
},
{
path: '/login',
name:'login',
meta: {
index: 2
},
component: () => import('@/views/Login/index.vue')
},
{
path: '/preferential',
name: 'preferential',
meta: {
index: 1
},
component: () => import('@/views/Preferential/index.vue')
},
{
path: '/cart',
name: 'cart',
meta: {
index: 1
},
component: () => import('@/views/Cart/index.vue')
},
{
path: '/user',
name: 'user',
meta: {
index: 1,
isPass: true
},
component: () => import('@/views/User/index.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
实现的效果:
- 使用vue的
transition
组件,在定义router时设置meta.index
数值来判断切换动画的使用哪种效果 - 使用vue的
keepailve
组件,在定义router时设置meta.keepalive
数值来判断是否要进行组件的缓存
转载自:https://juejin.cn/post/7258193813675671589