问题背景
近期项目研发vue的技术栈从vue2切换至vue3,部分写法升级。项目调试时发现页面缓存 不生效,页面使用setup语法糖(<script setup>
即组合式api
简化写法)。定位解决过程做一个记录。
定位问题
在vue2中页面缓存使用如下
js
//router.js 定义路由时在meta中增加cachePage配置项,将需要缓存的页面name遍历导出
const routes = [
{
path: '/neterror',
component: () => import('@/views/errorPage/NetError.vue'),
name: 'NetError',
meta: {
title: '网络异常',
cachePage:true
}
}
]
let cachePages = []
for(let route of routes) {
if(route.meta.cachePage){
cachePage0.push(route.name)
}
}
export const cachePage = cachePages
html
<!-- layout.vue cachePage为需要缓存的name数组 如['NetError'],从router.js import进来 -->
<keep-alive :include="cachePage">
<router-view />
</keep-alive>
在vue3中依样画葫芦
router还是用的js,写法一样
layout.vue里写法稍稍不一样,如下。在vue3里
<transition>
或<keep-alive>
不再直接包裹<router-view>
,<keep-alive>
需要通过插槽接收动态组件。
html
<!-- 页面主体 -->
<router-view v-slot="{ Component }">
<keep-alive :include="cachePage">
<component :is="Component" />
</keep-alive>
</router-view>
此时检查了cachePage的打印均无错误,但是缓存不生效。当把include去掉,缓存是有效果的。因此,定位是include引起的缓存未生效,而include只是组件名的数组,在使用setup语法糖时并未设置组件的name属性,从这里入手调试解决。
解决思路
vue2只有选项式api
写法,而vue3保留了这种写法,同时增加了组合式api
。在选项式api
写法中,我们写组件时会显性命名。
xml
<script>
export default{
name: 'Home' // 组件名称
}
</script>
而在使用setup语法糖后,无法优雅的定义组件的name值。虽然vite会根据组件的文件名自动生成组件名(文件名为 index.vue
时,组件名称会自动设置为 Index
),但有时不太符合预期,如home/index.vue的name期望是Home而不是Index。
为解决此问题,装了一个插件vite-plugin-vue-setup-extend,通过<script setup name="Home">
这样的方式指定组件名称,当然name需要和cachePage(即router.js中定义的路由的name)一致。(项目版本 vue:3.2.37)
sh
#安装插件依赖
npm i vite-plugin-vue-setup-extend@0.4.0 -D
js
//vite.config.js 引入依赖
import { defineConfig } from 'vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
export default
defineConfig({
plugins: [
VueSetupExtend()
]
})
html
<!--页面代码-->
<template>
···
</template>
<script setup name="Home">
···
</script>
vue3.3+版本也可在<script setup>
使用defineOptions定义name
js
<script setup>
import { defineOptions } from 'vue';
defineOptions({ name: 'Home' });
</script>
总结
在vue3项目中,使用<keep-alive>
缓存路由组件时,需要注意其写法,include
属性使用时需注意组件名称的设置等。