国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

淺談Vue頁面級緩存解決方案feb-alive(上)

2024-05-06 15:40:42
字體:
來源:轉載
供稿:網友

feb-alive

github地址
體驗鏈接

使用理由

開發者無需因為動態路由或者普通路由的差異而將數據初始化邏輯寫在不同的鉤子里beforeRouteUpdate或者activated 開發者無需手動緩存頁面狀態,例如通過localStorage或者sessionStorage緩存當前頁面的數據 feb-alive會幫你處理路由meta信息的存儲與恢復

為什么開發feb-laive?

當我們通過Vue開發項目時候,是否會有以下場景需求?

/a跳轉到/b 后退到/a時候,希望從緩存中恢復頁面 再次跳轉到/b時,分兩種情況 情況一: 通過鏈接或者push跳轉,則希望重新創建/b頁面,而不是從緩存中讀取 情況二: 如果點擊瀏覽器自帶前進按鈕,則還是從緩存中讀取頁面。

這個場景需求著重強調了緩存,緩存帶來的好處是,我上次頁面的數據及狀態都被保留,無需在從服務器拉取數據,使用戶體驗大大提高。

嘗試用keep-alive實現頁面緩存

<keep-alive> <router-view></router-view></keep-alive>

so easy但是理想很完美,現實很殘酷

存在問題

-/a跳到/b,再跳轉到/a 的時候,頁面中的數據是第一次訪問的/a頁面,明明是鏈接跳轉,確出現了緩存的效果,而我們期望的是像app一樣開啟一個新的頁面。

同理動態路由跳轉/page/1->/page/2因為兩個頁面引用的是同一個組件,所以跳轉時頁面就不會有任何改變,因為keep-alive的緩存的key是根據組件來生成的(當然Vue提供了beforeRouteUpdate鉤子供我們刷新數據) 總結:keep-alive的緩存是==組件級別==的,而不是==頁面級別==的。

舉個應用場景

例如瀏覽文章頁面,依次訪問3篇文章

/artical/1 /artical/2 /artical/3

當我從/artical/3后退到/artical/2時候,由于組件緩存,此時頁面還是文章3的內容,所以必須通過beforeRouteUpdate來重新拉取頁面2的數據。(注意此處后退不會觸發組件的activated鉤子,因為兩個路由都渲染同個組件,所以實例會被復用,不會執行reactivateComponent)

如果你想從/artical/3后退到/artical/2時,同時想恢復之前在/artical/2中的一些狀態,那么你還需要自己針對/artical/2中的所有狀態數據進行存儲和恢復。

綜上:keep-alive實現的組件級別的緩存和我們想象中的緩存還是有差距的,keep-alive并不能滿足我們的需求。

==針對這些問題,所以feb-alive插件誕生了==

由于feb-alive是基于keep-alive實現的,所以我們先簡單分析一下keep-alive是如何實現緩存的

export default { name: 'keep-alive', abstract: true, props: { include: patternTypes, exclude: patternTypes, max: [String, Number] }, created () { this.cache = Object.create(null) this.keys = [] }, destroyed () { for (const key in this.cache) {  pruneCacheEntry(this.cache, key, this.keys) } }, mounted () { this.$watch('include', val => {  pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => {  pruneCache(this, name => !matches(val, name)) }) }, render () { // 獲取默認插槽 const slot = this.$slots.default // 獲取第一個組件,也就和官方說明的一樣,keep-alive要求同時只有一個子元素被渲染,如果你在其中有 v-for 則不會工作。 const vnode: VNode = getFirstComponentChild(slot) // 判斷是否存在組件選項,也就是說只對組件有效,對于普通的元素則直接返回對應的vnode const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions if (componentOptions) {  // 檢測include和exclude  const name: ?string = getComponentName(componentOptions)  const { include, exclude } = this  if (  // not included  (include && (!name || !matches(include, name))) ||  // excluded  (exclude && name && matches(exclude, name))  ) {  return vnode  }  const { cache, keys } = this  // 如果指定了子組件的key則使用,否則通過cid+tag生成一個key  const key: ?string = vnode.key == null  ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')  : vnode.key  // 判斷是否存在緩存  if (cache[key]) {  // 直接復用組件實例,并更新key的位置  vnode.componentInstance = cache[key].componentInstance  remove(keys, key)  keys.push(key)  } else {  // 此處存儲的vnode還沒有實例,在之后的流程中通過在createComponent中會生成實例  cache[key] = vnode  keys.push(key)  // 當緩存數量大于閾值時,刪除最早的key  if (this.max && keys.length > parseInt(this.max)) {   pruneCacheEntry(cache, keys[0], keys, this._vnode)  }  }  // 設置keepAlive屬性,createComponent中會判斷是否已經生成組件實例,如果是且keepAlive為true則會觸發actived鉤子。  vnode.data.keepAlive = true } return vnode || (slot && slot[0]) }}            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 杭州市| 郁南县| 顺义区| 保靖县| 于田县| 喀喇沁旗| 凤台县| 达拉特旗| 酒泉市| 盐城市| 南京市| 明光市| 长白| 宜州市| 山东省| 大洼县| 噶尔县| 金山区| 彭水| 庆城县| 黄平县| 商都县| 淄博市| 郁南县| 新河县| 锡林郭勒盟| 上犹县| 邯郸县| 海门市| 巴林右旗| 永和县| 河池市| 班玛县| 贞丰县| 桃江县| 通榆县| 甘肃省| 共和县| 南宫市| 吉木乃县| 昌都县|