如何巧用Vue緩存函數淺析
vue2中的緩存函數
vue2版本中有這么一個緩存函數
/** * Create a cached version of a pure function. */ function cached (fn) { var cache = Object.create(null); return (function cachedFn (str) { var hit = cache[str]; return hit || (cache[str] = fn(str)) }) }
上面這個函數存在一個常用場景,比如存在一個數組,需要把每個元素的首字母轉為大寫。
const array = ['abc', 'ed', 'abc', 'acd', 'ed', 'fkg', ...];
常用的解決方法
// 定一個capitalize函數 function capitalize (str) { return str.charAt(0).toUpperCase() + str.slice(1) }; const capitalizeArray = array.map(capitalize);
細心的我們會發(fā)現array中存在不少重復的元素, 他們返回的結果一樣的,實際不需要重復計算執(zhí)行capitalize,而且capitalize是一個PURE函數,此時我們可以利用上面的cached做一個備忘錄的功能。
改造如下
function capitalize (str) { return str.charAt(0).toUpperCase() + str.slice(1) }; const capitalizeArray = array.map(cached(capitalize));
當遇到重復字符串的時候會直接返回緩存的結果。想想capitalize是一個十分耗時的任務,性能優(yōu)化不止一點點。
改造vue緩存函數
上面的舉例是緩存同步任務的純函數,在業(yè)務開發(fā)中存在這么一個場景,輸入框搜索。當輸入框觸發(fā)input事件的時候,我們都會調用接口返回查詢結果。比如我輸入了掘金關鍵字返回了結果,然后又輸入掘金NBA返回了結果,此時我刪掉了NBA,又查詢掘金, 實際上這個結果我們之前查過,如果緩存起來直接拉緩存即可,不用再去調用接口。
我們基于cached實現一個緩存異步純函數的備忘錄
const cachedAsync = function(fn) { const cache = Object.create(null); return async str => { const hit = cache[str]; if (hit) { return hit; } // 只緩存成功的Promise, 失敗直接重新請求 return (cache[str] = await fn(str)); }; };
使用場景
const cachedAsyncQueryPrdList = cachedAsync(prdNo => { // 下面是一個請求的操作,返回一個promise return queryPrdList({ prdNo }); }); <template> <el-input v-model="prdNo" placeholder="請輸入產品編碼" @input="handleQueryPrdList" /> <el-select> <el-option v-for="item in prdList" :label="item.label" :value="item.value"> </el-select> </template> <script> export default { data() { prdNo: '', prdList: [], }, methods: { async handleQueryPrdList() { const { data } = await cachedAsyncQueryPrdList(this.prdNo); this.prdList = data; } } } </script>
上面實現了,當輸入相同的關鍵字,如果之前請求是成功的,直接拉起緩存,不會重新向服務器發(fā)起請求。因為我們的備忘錄只會緩存成功的promise。
優(yōu)化
針對上面的場景,雖然el-input底層已經使用compositionEnd和compositionStart事件來做一層防抖,只有文字真正輸入到屏幕上才會去觸發(fā)input事件。但是這是不夠,如果用戶輸入手速很快,會出現一秒發(fā)幾次請求的情況,增加了服務器負擔。因此這種一般會搭配防抖函數使用。
防抖函數
const debounce = (fn, ms = 300) => { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => fn.apply(this, args), ms); }; };
然后搭配我們的cachedAsync使用
const cachedAsyncQueryPrdList = cachedAsync(prdNo => { // 下面是一個ajax請求的操作,返回一個promise return queryPrdList({ prdNo }); }); <template> <el-input v-model="prdNo" placeholder="請輸入產品編碼" @input="debounceQueryPrdListFn" /> <el-select> <el-option v-for="item in prdList" :label="item.label" :value="item.value"> </el-select> </template> <script> const noop = () => {}; export default { data() { prdNo: '', prdList: [], debounceQueryPrdListFn: noop, }, created() { this.debounceQueryPrdListFn = debounce(this.handleQueryPrdList); }, methods: { async handleQueryPrdList() { const { data } = await cachedAsyncQueryPrdList(this.prdNo); this.prdList = data; } } } </script>
FBI WARNING: >>> cachedAsync函數,只適用于PURE函數。
這個實現已經在生產環(huán)境穩(wěn)定使用,大家可以放心食用。
總結
到此這篇關于如何巧用Vue緩存函數的文章就介紹到這了,更多相關巧用Vue緩存函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
postcss-pxtorem設置不轉換UI框架的CSS單位問題
這篇文章主要介紹了postcss-pxtorem設置不轉換UI框架的CSS單位問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07