【转】【keep-alive】如何一步一步解决keep-alive缓存不生效问题

181 阅读3分钟

原文地址:【keep-alive】如何一步一步解决keep-alive缓存不生效问题 - 掘金 (juejin.cn)

问题描述:

需求: 子页面tab切换时希望保存组件状态,不重新刷新

问题: keep-alive缓存不生效

项目背景:【VUE3】+【Vite】+【ruoyi后台管理系统】

解决步骤:

一、保证keep-alive直接包裹组件

因为keep-alive会判断第一层dom是不是组件,如果包裹了一层div,则会缓存失败;

之前的代码中,keep-alive和component之间加了一层div,现在将这个div往外挪了一层

xml
复制代码
<router-view v-slot="{ Component, route }">
     <transition name="fade-transform" mode="out-in">
 <!-- transition需要一个根节点,所以之前代码中keep-alive和component之间加了一层div,现在将这个div往外挪了一层 -->
          <div>
              <keep-alive>
                   <component v-if="!route.meta.link" :is="Component" :key="route.path" />
              </keep-alive>
          </div>
     </transition>
</router-view>

以上为第一步,配置完成后,在无include参数情况下,缓存生效,但如果无include参数,刷新功能(通过将include移除view后,nextTick()中移入来实现)无法实现。所以。

二、进一步解决include配置不生效问题

ini
复制代码
<keep-alive :include="(tagsViewStore.cachedViews as any)">
    <component v-if="!route.meta.link" :is="Component" :key="route.path" />
</keep-alive>

(一)一般而言,keep-alive不生效,有两个思路:

第一,是否name配置不对

keep-alive的include和exclude属性都是通过单文件组件中的name属性来判断是否缓存此组件;

第二,是否router-view嵌套超过两层。

若超过,要在子级router-view处添加一层keep-alive。

(二)具体问题具体分析:

1,我的项目中,router-view只有两层,且在不配置include时候,缓存生效,所以排除2,问题大概率是出现在name上;

2,核对了路由中的name和组件页面中的name,是否一致的。

arduino
复制代码
//SFC中配置
<script lang="ts" name="dailyClear" setup>
json
复制代码
//路由中配置
{
   "name": "dailyClear",
    "path": "dailyClear",
   "hidden": false,
   "component": "review/dailyClear/index",
   "meta": {
            "title": "日清分单核对",
             "icon": "",
             "noCache": false,
             "link": null,
              "private": true
           }
},

3,通过console打印tagsViewStore.cachedViews中值,确认取值是否正确

以上三步均无问题,但include配置仍然不生效

(三)新的思路:SFC中的name配置是否成功

arduino
复制代码
//SFC中配置
<script lang="ts" name="dailyClear" setup>

之前没用过vue3的setup中配置name的写法

于是查了一下,如何配置,结果如下:

第一种:新增加一个script标签,在这个标签中写入name属性,代码如下:

xml
复制代码
<script lang="ts"> 
    export default { name: "TButton", }; 
</script> 

<script lang="ts" setup> 
//to do
</script>

第二种:使用 unplugin-vue-define-option 插件:

scss
复制代码
//三步走:
//1,安装:npm install vite-plugin-vue-setup-extend -D
//2,集成:在vite.config.ts中配置plugin
export default defineConfig({ 
    plugins: 
    [
        vue(), 
        vueSetupExtend()
## ]
})
//3,如下,在页面中配置defineOptions
<script lang="ts" setup> 
    defineOptions({ name: 'TButton', }); 
</script>

第三种:使用 vite-plugin-vue-setup-extend 插件(最优雅):

arduino
复制代码
//安装配置同上,在页面中使用如下
<script lang="ts" name="dailyClear" setup>

发现和我原有项目中配置name的方式一致,但是我的package.json中并无此插件

于是重新安装配置,重启项目后,keep-alive生效。

至此问题解决!!!

(此篇文章为解决问题思路记录,所以并不是按照知识结构来写,而是按照我解决问题时一步一步的思维方向为导向的,如有不妥,望海涵!)

作者:Coco小汪汪
链接:juejin.cn/post/717394…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。