Vue3手動清理keep-alive組件緩存的方法詳解
Vue3中手動清理keep-alive組件緩存的一個解決方案
源碼
if ((process.env.NODE_ENV !== 'production') || __VUE_PROD_DEVTOOLS__) {
instance.__v_cache = cache;
}
//省略一些代碼...
function pruneCacheEntry(key) {
const cached = cache.get(key);
if (!current || cached.type !== current.type) {
unmount(cached);
}
else if (current) {
// current active instance should no longer be kept-alive.
// we can't unmount it now but it might be later, so reset its flag now.
resetShapeFlag(current);
}
cache.delete(key);
keys.delete(key);
}
這里表明我們有兩種修改方案:
方案一:注釋 instance.__v_cache = cache; 這行代碼的判斷條件,也就是注釋掉它的if判斷,這樣無論在什么環(huán)境,我們都可以取到__v_cache對象,這樣就可以按照上一篇的方案來解決手動釋放的問題
方案二:注意到源碼中的pruneCacheEntry函數(shù)就是通過key來釋放緩存,所以如果僅僅是想通過key來釋放緩存,那么可以通過將pruneCacheEntry函數(shù)暴露出來實現(xiàn)我們的要求
方案一
修改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"
);
//使用同步讀取文件
let data = fs.readFileSync(vue_bundler_file, "utf8");
//如果未添加過
if (data.indexOf("http://__v_cache") < 0) {
console.log("正在修改源碼文件:", vue_bundler_file);
//先找到__v_cache變量的位置
let index = data.indexOf("__v_cache");
if (index >= 0) {
// 繼續(xù)往前找if關鍵字
index = data.lastIndexOf("if ", index);
if (index >= 0) {
//從上一個位置開始
index -= 1;
//然后放一個注釋
const comment = " //__v_cache ";
//然后拼接
data = data.substring(0, index) + comment + data.substring(index);
//繼續(xù)往后找下一個大括號 }
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);
}
然后重新啟動運行項目,就可以按照上一篇的方式,通過 __v_cache 對象來手動清理keep-alive的緩存了。
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,
};
},
};
如果打開 node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js 文件,搜索 __v_cache ,會看到這樣的代碼片段:

方案二
在 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) {
// 繼續(xù)找下一個大括號 }
index = data.indexOf("}", index);
if (index >= 0) {
//從下一個位置開始
index += 1;
//然后放一個可以釋放的函數(shù)
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);
}
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) {
// 繼續(xù)找下一個大括號 }
index = data.indexOf("}", index);
if (index >= 0) {
//從下一個位置開始
index += 1;
//然后放一個可以釋放的函數(shù)
const remove =
" sharedContext.$pruneCacheEntry = function(key) {\r\n" +
" const cached = cache.get(key);\r\n" +
" if (cached) {\r\n" +
" if (cached.key == current?.key) {\r\n" +
" resetShapeFlag(current);\r\n" +
" } else {\r\n" +
" unmount(cached);\r\n" +
" }\r\n" +
" cache.delete(key);\r\n" +
" keys.delete(key);\r\n" +
" }\r\n" +
" }\r\n"
//然后拼接
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);
}
之后,我們項目重新運行后,就可以通過ref取到keep-alive組件的引用,然后使用這個引用對象直接使用$pruneCacheEntry函數(shù)來刪除指定key的緩存了:
this.$refs.keepAlive.$pruneCacheEntry("key")如果打開 node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js 文件,搜索 __v_cache ,會看到這樣的代碼片段:

結語
目前,目前還沒有找到更好的解決方案,我自己采用的是第二種方案,算是暫時解決了問題,當然,兩種方案可以結合使用。
到此這篇關于Vue3手動清理keep-alive組件緩存的方法詳解的文章就介紹到這了,更多相關Vue3清理keep-alive組件緩存內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vite.config.ts配置之自動導入element-puls方式
這篇文章主要介紹了vite.config.ts配置之自動導入element-puls方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
vue2.0與bootstrap3實現(xiàn)列表分頁效果
這篇文章主要為大家詳細介紹了vue2.0與bootstrap3實現(xiàn)列表分頁效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11
vue.js頁面加載執(zhí)行created,mounted的先后順序說明
這篇文章主要介紹了vue.js頁面加載執(zhí)行created,mounted的先后順序說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
vue.js中proxyTable 轉發(fā)請求的實現(xiàn)方法
今天小編就為大家分享一篇vue.js中proxyTable 轉發(fā)請求的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09

