场景
管理后台使用tags的形式打开页面,存在不同路由复用同一组件的情况。
原始的keep-alive使用include,是通过path匹配页面组件的name实现,name默认是根据文件名自动生成,include剔除路由时,会把想通name的组件缓存清除,导致已有缓存丢失。
官方未提供api等解决方案,on Aug 15, 2021已有prgithub.com/vuejs/core/…
keep-alive源码位置:github.com/vuejs/core/…
最终选择方案三,暴露keep-alive缓存删除方法。
方案一:
复制keepalive组件重写,使其缓存匹配通过key识别;使用includeKey 识别。
juejin.cn/post/714006…
github.com/meadmin-cn/…
缺点:
全文件复制,文件过多。
不满足特殊场景,如新开页面编辑,回到列表页需要刷新
方案二:
获取keepalive的cache,进行处理集中。非dev环境,未能暴露cache。
在vue.config.js增加配置修改对应文件,暴露__v_cache
const path = require("path");
const fs = require("fs");
try {
const vue_bundler_file = path.resolve(
__dirname,
"node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js"
);
//使用同步读取文件
let data = fs.readFileSync(vue_bundler_file, "utf8");
//如果未添加过
if (data.indexOf("//__v_cache") < 0) {
console.log("正在修改源码文件:", vue_bundler_file);
//先找到__v_cache变量的位置
let index = data.indexOf("__v_cache");
if (index >= 0) {
// 继续往前找if关键字
index = data.lastIndexOf("if ", index);
if (index >= 0) {
//从上一个位置开始
index -= 1;
//然后放一个注释
const comment = " //__v_cache ";
//然后拼接
data = data.substring(0, index) + comment + data.substring(index);
//继续往后找下一个大括号 }
index = data.indexOf("}", index);
if (index >= 0) {
//从上一个位置开始
index -= 1;
//然后拼接
data = data.substring(0, index) + comment + data.substring(index);
}
fs.writeFileSync(vue_bundler_file, data, "utf8");
}
}
}
} catch (er) {
console.error(er.message);
}
export default {
setup() {
const instance = getCurrentInstance();
const handler = new KeepAliveHandler();
onMounted(() => {
const keepAlive = instance.refs.keepAlive;
handler.bind(keepAlive);
});
const remove = (key) => {
handler.remove(key);
};
return {
remove,
};
},
};
方案三:
使keepalive暴露删除方法pruneCacheEntry。使用暴露的删除缓存方法,全缓存情况下,fullPath作为key值,按需处理页面缓存需要。
taglist减少或单独关闭tag页时调用pruneCacheEntry;特殊需要(如编辑),清除对应路由缓存。
vue.config.js增加配置修改对应文件
const path = require("path");
const fs = require("fs");
try {
const vue_bundler_file = path.resolve(
__dirname,
"node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js"
);
//使用同步读取文件
const data = fs.readFileSync(vue_bundler_file, "utf8");
//如果未添加过
if (data.indexOf("sharedContext.$pruneCacheEntry") < 0) {
console.log("正在修改源码文件:", vue_bundler_file);
//先找到__v_cache变量的位置
let index = data.indexOf("__v_cache");
if (index >= 0) {
// 继续找下一个大括号 }
index = data.indexOf("}", index);
if (index >= 0) {
//从下一个位置开始
index += 1;
//然后放一个可以释放的函数
const remove =
" sharedContext.$pruneCacheEntry = (key) => cache.get(key) && pruneCacheEntry(key);";
//然后拼接
const result =
data.substring(0, index) +
"\r\n" +
remove +
"\r\n" +
data.substring(index);
fs.writeFileSync(vue_bundler_file, result, "utf8");
}
}
}
} catch (er) {
console.error(er.message);
}
<router-view #="{ Component, route }">
<keep-alive ref="keepAlive">
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</router-view>
if (this.$refs.keepAlive.$pruneCacheEntry) {
this.$store.commit('SET_PRUNE', this.$refs.keepAlive.$pruneCacheEntry);
}
遇到问题,本地vite开发,会存在文件构建缓存(.vite/.deps),方法未暴露成功, --fore编译启动可清除构建缓存,或增加production启动后,再恢复。