欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue2.x中keep-alive源碼解析(實(shí)例代碼)

 更新時(shí)間:2023年02月14日 10:48:04   作者:不叫貓先生  
Keep-Alive模式避免頻繁創(chuàng)建、銷毀鏈接,允許多個(gè)請(qǐng)求和響應(yīng)使用同一個(gè)HTTP鏈接,這篇文章主要介紹了vue2.x中keep-alive源碼解析,需要的朋友可以參考下

一、前世塵緣

vue中內(nèi)置組件keep-alive的設(shè)計(jì)思想源于HTTP中的Keep-Alive模式,Keep-Alive模式避免頻繁創(chuàng)建、銷毀鏈接,允許多個(gè)請(qǐng)求和響應(yīng)使用同一個(gè)HTTP鏈接。
HTTP 1.0 中keep-alive默認(rèn)是關(guān)閉的,需要在HTTP頭加入"Connection: Keep-Alive",才能啟用Keep-Alive;HTTP 1.1中默認(rèn)啟用Keep-Alive,如果加入"Connection: close ",才關(guān)閉。目前大部分瀏覽器都是用HTTP 1.1協(xié)議。

二、keep-alive內(nèi)置組件

作用:動(dòng)態(tài)切換組件時(shí)緩存組件實(shí)例,避免dom重新渲染。

1.緩存動(dòng)態(tài)組件

當(dāng)組件為componentOne時(shí)緩存該組件實(shí)例

<keep-alive :include="componentOne`" :exclude="componentTwo" :max="num"> 
    <component :is="currentComponent"></component> 
</keep-alive>

2.緩存路由組件

注意緩存路由組件vue2.x與vue3.x有區(qū)別,vue2.x用法如下:

<keep-alive :include="componentOne`" :exclude="componentTwo" :max="num"> 
    <router-view :is="currentComponent"></router-view> 
</keep-alive>

vue3.x用法如下:

<router-view v-slot="{ Component }">
   <keep-alive :include="includeList">
	    <component :is="Component"/>
   </keep-alive>
</router-view>

3.原理解析

緩存的組件以 [key,vnode] 的形式記錄,keys記錄緩存的組件key,依據(jù)inclued、exclude的值,并且當(dāng)超過(guò)設(shè)置的max根據(jù)LUR算法進(jìn)行清除。vue2.x和vue3.x相差不大。

(1)keep-alive 在生命周期中做了什么?

  • created:初始化catch,keys。catch是一個(gè)緩存組件虛擬dom的數(shù)組,其中數(shù)組中對(duì)象的key是組件的key,value是組件的虛擬dom;keys是一個(gè)用來(lái)緩存組件的key的數(shù)組。
  • mounted:實(shí)時(shí)監(jiān)聽(tīng)include、exclude屬性的變化,并執(zhí)行相應(yīng)操作。
  • destroyed:刪除掉所有緩存相關(guān)的數(shù)據(jù)。

(2)源碼

地址:源碼地址

// 源碼位置:src/core/components/keep-alive.js
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 () {
   //查看是否有緩存沒(méi)有緩存的話直接走緩存
    this.cacheVNode()
    // 這里借助 watch 監(jiān)控 include  和 exclude 
  // 如果有變化的話,則按照最新的 include 和 exclude 更新 this.cache
  // 將不滿足 include、exclude 限制的 緩存vnode 從 this.cache 中移除  
  this.$watch('include', val => {
      pruneCache(this, name => matches(val, name))
    })
    this.$watch('exclude', val => {
      pruneCache(this, name => !matches(val, name))
    })
  },
  updated() {
    this.cacheVNode()
  },
  methods:{
   cacheVNode() {
      const { cache, keys, vnodeToCache, keyToCache } = this
      if (vnodeToCache) {
        const { tag, componentInstance, componentOptions } = vnodeToCache
        cache[keyToCache] = {
          name: _getComponentName(componentOptions),
          tag,
          componentInstance
        }
        keys.push(keyToCache)
        // prune oldest entry
        if (this.max && keys.length > parseInt(this.max)) {
          pruneCacheEntry(cache, keys[0], keys, this._vnode)
        }
        this.vnodeToCache = null
      }
    }
 },
  render(){
    //下面詳細(xì)介紹
  }
}

(3)abstract:true

設(shè)置為true時(shí),表面該組件為抽象組件,抽象組件不會(huì)和子組件建立父子關(guān)系,組件實(shí)例會(huì)根據(jù)這個(gè)屬性決定是否忽略該組件,所以并不會(huì)有節(jié)點(diǎn)渲染在頁(yè)面中。

(4)pruneCacheEntry函數(shù)

destoryed周期中循環(huán)了所有緩存的組件,并用 pruneCacheEntry進(jìn)行處理,pruneCacheEntry做了什么事?

// src/core/components/keep-alive.js

function pruneCacheEntry (
  cache: VNodeCache,
  key: string,
  keys: Array<string>,
  current?: VNode
) {
  const cached = cache[key]
  if (cached && (!current || cached.tag !== current.tag)) {
    cached.componentInstance.$destroy() // 執(zhí)行組件的destory鉤子函數(shù)
  }
  cache[key] = null  // cache中對(duì)象的key設(shè)為null
  remove(keys, key) // 刪除keys對(duì)應(yīng)的元素
}

destoryed周期中,刪除緩存組件的所有數(shù)組,pruneCacheEntry主要做了這幾件事:

  • 遍歷緩存組件集合(cach),對(duì)所有緩存的組件執(zhí)行$destroy方法
  • 清除cache中key的值
  • 清除keys中的key

(5)render

render中主要做了什么?

  • 獲取keep-alive組件子節(jié)點(diǎn)中第一個(gè)組件的vnode、componentOptions、name
  • 如果name存在且不在include中或者存在在exclude中,則返回虛擬dom。此時(shí)該組件并沒(méi)有使用緩存。
  • 接下來(lái)就是上面的else情況:使用keep-alive進(jìn)行組件緩存,根據(jù)組件id,tag生成組件的key,如果cache集合中存在以key為屬性名的vdom,,說(shuō)明組件已經(jīng)緩存過(guò),則將緩存的 Vue 實(shí)例賦值給 vnode.componentInstance,從keys中刪除key,再把key push導(dǎo)keys中,保證當(dāng)前key在keys的最后面(這是LRU算法的關(guān)鍵)。如果不存在則繼續(xù)走下面
  • 如果cach[key]不存在則為第一次加載組件,則把vdom賦值給cach[key],key push到key
  • 如果keys的長(zhǎng)度大于max,則進(jìn)行組件緩存清理,則把不經(jīng)常使用的被緩存下來(lái)的在keys中排第一位的組件清除掉,清除也是調(diào)用的pruneCacheEntry方法
render () {
	// 獲取 keep-alive 組件子節(jié)點(diǎn)中的第一個(gè)組件 vnode
    const slot = this.$slots.default
    const vnode = getFirstComponentChild(slot)
    // 獲取組件的配置選項(xiàng)對(duì)象
    const componentOptions = vnode && vnode.componentOptions
    if (componentOptions) {
      // 獲取組件的名稱
      const name = _getComponentName(componentOptions)
      const { include, exclude } = this
       // 如果當(dāng)前的組件 name 不在 include 中或者組件的 name 在 exclude 中
		  // 說(shuō)明當(dāng)前的組件是不被 keep-alive 所緩存的,此時(shí)直接 return vnode 即可
      if (
        // not included
        (include && (!name || !matches(include, name))) ||
        // excluded
        (exclude && name && matches(exclude, name))
      ) {
        return vnode
      }
     // 代碼執(zhí)行到這里,說(shuō)明當(dāng)前的組件受 keep-alive 組件的緩存
      const { cache, keys } = this
        // 定義 vnode 緩存用的 key
      const key =
        vnode.key == null
          ? // same constructor may get registered as different local components
            // so cid alone is not enough (#3269)
            componentOptions.Ctor.cid +
            (componentOptions.tag ? `::${componentOptions.tag}` : '')
          : vnode.key
           // 如果 cache[key] 已經(jīng)存在的話,則說(shuō)明當(dāng)前的組件 vnode 已經(jīng)被緩存過(guò)了,此時(shí)需要將其恢復(fù)還原出來(lái)
      if (cache[key]) {
      	// 將緩存的 Vue 實(shí)例賦值給 vnode.componentInstance
        vnode.componentInstance = cache[key].componentInstance
        // make current key freshest
        	// 先從 keys 中移除 key,然后再 push key,這可以保證當(dāng)前的 key 在 keys 數(shù)組中的最后面
        remove(keys, key)
        keys.push(key)
      } else {
        // delay setting the cache until update
        	// 如果 cache[key] 不存在的話,說(shuō)明當(dāng)前的子組件是第一次出現(xiàn),此時(shí)需要將 vnode 緩存到 cache 中,將 key 存儲(chǔ)到 keys 字符串?dāng)?shù)組中。這里是用一個(gè)中間變量接收,當(dāng)數(shù)據(jù)變化時(shí)觸發(fā)updated去調(diào)用cacheVNode方法。
        this.vnodeToCache = vnode
        this.keyToCache = key
      }

      // @ts-expect-error can vnode.data can be undefined
       // 將 vnode.data.keepAlive 屬性設(shè)置為 true,這對(duì) vnode 有一個(gè)標(biāo)識(shí)的作用,標(biāo)識(shí)這個(gè)
		  // vnode 是 keep-alive 組件的 render 函數(shù) return 出去的,這個(gè)標(biāo)識(shí)在下面的運(yùn)行代碼中有用
      vnode.data.keepAlive = true
    }
    return vnode || (slot && slot[0])
  }

三、LRU算法

緩存的組件在進(jìn)行清除的時(shí)候使用了LRU算法,具體是什么策略呢?當(dāng)數(shù)據(jù)超過(guò)了限定空間的時(shí)候?qū)?shù)據(jù)清理,清理的原則是對(duì)很久沒(méi)有使用到過(guò)的數(shù)據(jù)進(jìn)行清除

到此這篇關(guān)于vue2.x中keep-alive源碼解析的文章就介紹到這了,更多相關(guān)vue2.x keep-alive源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue如何使用AIlabel標(biāo)注組件

    vue如何使用AIlabel標(biāo)注組件

    這篇文章主要介紹了vue如何使用AIlabel標(biāo)注組件,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue權(quán)限指令控制權(quán)限詳解

    Vue權(quán)限指令控制權(quán)限詳解

    因?yàn)轫?xiàng)目中需要根據(jù)后端返回的權(quán)限進(jìn)行功能的顯示隱藏,所以就加了個(gè)權(quán)限指令。不用寫(xiě)if else進(jìn)行判斷,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-09-09
  • 如何修改vue-treeSelect的高度

    如何修改vue-treeSelect的高度

    這篇文章主要介紹了如何修改vue-treeSelect的高度,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Css中該如何使用Vue的變量

    Css中該如何使用Vue的變量

    在我們使用Vue開(kāi)發(fā)時(shí),經(jīng)常會(huì)用到CSS,下面這篇文章主要給大家介紹了關(guān)于Css中該如何使用Vue變量的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • vue實(shí)現(xiàn)商品列表的添加刪除實(shí)例講解

    vue實(shí)現(xiàn)商品列表的添加刪除實(shí)例講解

    在本篇內(nèi)容里小編給大家分享的是關(guān)于vue實(shí)現(xiàn)商品列表的添加刪除實(shí)例講解,有興趣的朋友們可以參考下。
    2020-05-05
  • vue3.0實(shí)現(xiàn)考勤日歷組件使用詳解

    vue3.0實(shí)現(xiàn)考勤日歷組件使用詳解

    這篇文章主要為大家詳細(xì)介紹了vue3.0實(shí)現(xiàn)考勤日歷組件使用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Vue3動(dòng)態(tài)倒計(jì)時(shí)的代碼實(shí)現(xiàn)

    Vue3動(dòng)態(tài)倒計(jì)時(shí)的代碼實(shí)現(xiàn)

    在使用Vue框架開(kāi)發(fā)Web應(yīng)用時(shí),倒計(jì)時(shí)功能是一個(gè)常見(jiàn)的需求,它可以在一定時(shí)間內(nèi)重復(fù)執(zhí)行某些操作,比如防止用戶重復(fù)提交表單、限制投票次數(shù)、實(shí)現(xiàn)驗(yàn)證碼獲取等功能,所以本文給大家介紹了Vue3動(dòng)態(tài)倒計(jì)時(shí)的代碼實(shí)現(xiàn),需要的朋友可以參考下
    2024-09-09
  • vue2項(xiàng)目解決IE、360瀏覽器兼容問(wèn)題的辦法

    vue2項(xiàng)目解決IE、360瀏覽器兼容問(wèn)題的辦法

    雖然已經(jīng)擯棄ie的使用,但是在現(xiàn)階段還是在某些場(chǎng)景下需要用到ie,這篇文章主要給大家介紹了關(guān)于vue2項(xiàng)目解決IE、360瀏覽器兼容問(wèn)題的辦法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • elementPlus中的Autocomplete彈出層錯(cuò)位問(wèn)題解決分析

    elementPlus中的Autocomplete彈出層錯(cuò)位問(wèn)題解決分析

    這篇文章主要介紹了elementPlus中的Autocomplete彈出層錯(cuò)位問(wèn)題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 如何把vuejs打包出來(lái)的文件整合到springboot里

    如何把vuejs打包出來(lái)的文件整合到springboot里

    這篇文章主要介紹了如何把vuejs打包出來(lái)的文件整合到springboot里,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07

最新評(píng)論