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

首頁 > 語言 > JavaScript > 正文

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

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

feb-alive

github地址
體驗鏈接

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

在剖析feb-alive實現之前,希望大家對以下基本知識有一定的了解。

keep-alive實現原理 history api vue渲染原理 vue虛擬dom原理

feb-alive與keep-alive差異性

1. 針對activated鉤子差異性

keep-alive配合vue-router在動態路由切換的情況下不會觸發activated鉤子,因為切換的時候組件沒有變化,所以只能通過beforeRouteUpdate鉤子或者監聽$route來實現數據更新,而feb-alive在動態路由切換時,依然會觸發activated鉤子,所以用戶可以放心的將業務更新邏輯寫在activated鉤子,不必關心動態路由還是非動態路由的情況。

2. feb-alive是頁面級緩存,而keep-alive是組件級別緩存

所以在上文中講到的使用keep-alive存在的一些限制問題都能夠得到有效的解決

實現原理

首先我們的目標很明確,需要開發的是一個頁面級別的緩存插件,之前使用keep-alive遇到的諸多問題,歸根結底是因為它是一個組件級別的緩存。那么我們就需要尋找每個頁面的特征,用來存儲我們需要存儲的路由組件vnode,這里我們就需要思考什么可以作為每個頁面的標記

兩種方式:

通過每個url的查詢參數來存儲key 通過history.state來存儲key

方案一:使用查詢參數

優點:

可以兼容vue-router的hash模式

缺點:

每個頁面的url后面都會帶一個查詢參數
每次頁面跳轉都需要重寫url

方案二:使用history.state

優點:

無需附帶額外的查詢參數

缺點:

不支持hash模式

相比方案一明顯的缺點,我更較傾向于方案二,舍棄hash模式的兼容性,換來整個插件更加好的用戶體驗效果。
接下來看下feb-alive的實現,feb-alive組件與上文的keep-alive一樣都是抽象組件,結構基本一致,主要區別在于render函數的

實現

// feb-alive/src/components/feb-alive.jsrender () {  // 取到router-view的vnode  const vnode = this.$slots.default ? this.$slots.default[0] : null  const disableCache = this.$route.meta.disableCache  // 如果不支持html5 history則不做緩存處理  if (!supportHistoryState) {    return vnode  }  // 嘗試寫入key  if (!history.state || !history.state[keyName]) {    const state = {      [keyName]: genKey()    }    const path = getLocation()    history.replaceState(state, null, path)  }  // 有些瀏覽器不支持往state中寫入數據  if (!history.state) {    return vnode  }  // 指定不使用緩存  if (disableCache) {    return vnode  }  // 核心邏輯  if (vnode) {    const { cache, keys } = this    const key = history.state[keyName]    const { from, to } = this.$router.febRecord    let parent = this.$parent    let depth = 0    let cacheVnode = Object.create(null)    vnode && (vnode.data.febAlive = true)    while (parent && parent._routerRoot !== parent) {      if (parent.$vnode && parent.$vnode.data.febAlive) {        depth++      }      parent = parent.$parent    }    // 記錄緩存及其所在層級    febCache[depth] = cache    // /home/a backTo /other    // 內層feb-alive實例會被保存,防止從/home/a 跳轉到 /other的時候內層feb-alive執行render時候,多生成一個實例    if (to.matched.length < depth + 1) {      return null    }    if (from.matched[depth] === to.matched[depth] && (from.matched.slice(-1)[0] !== to.matched.slice(-1)[0])) {      // 嵌套路由跳轉 && 父級路由      // /home/a --> /home/b      // 父路由通過key進行復用      cache[key] = cache[key] || this.keys[this.keys.length - 1]      cacheVnode = getCacheVnode(cache, cache[key])      if (cacheVnode) {        vnode.key = cacheVnode.key        remove(keys, key)        keys.push(key)      } else {        this.cacheClear()        cache[key] = vnode        keys.push(key)      }    } else {      // 嵌套路由跳轉 && 子路由      // 正常跳轉 && 動態路由跳轉      // /a --> /b      // /page/1 --> /page/2      vnode.key = `__febAlive-${key}-${vnode.tag}`      cacheVnode = getCacheVnode(cache, key)      // 只有相同的vnode才允許復用組件實例,否則雖然實例復用了,但是在patch的最后階段,會將復用的dom刪除      if (cacheVnode && vnode.tag === cacheVnode.tag) {        // 從普通路由后退到嵌套路由時,才需要復原key        vnode.key = cacheVnode.key        vnode.componentInstance = cacheVnode.componentInstance        remove(keys, key)        keys.push(key)      } else {        this.cacheClear()        cache[key] = vnode        keys.push(key)      }    }    vnode.data.keepAlive = true  }  return vnode}            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 娄烦县| 麟游县| 综艺| 陈巴尔虎旗| 井研县| 炎陵县| 芦山县| 新余市| 富民县| 定襄县| 江口县| 莆田市| 顺平县| 丹寨县| 台江县| 红原县| 青阳县| 呼玛县| 宜春市| 云浮市| 道孚县| 仁寿县| 宣城市| 东方市| 永春县| 敖汉旗| 台前县| 新干县| 延长县| 汤阴县| 龙游县| 吉隆县| 蓬莱市| 牟定县| 科技| 博客| 英吉沙县| 柳河县| 九龙坡区| 海原县| 左贡县|