搜尋
首頁web前端Vue.js聊聊對vue內建組件keep-alive的理解

聊聊對vue內建組件keep-alive的理解

Dec 14, 2022 pm 08:15 PM
javascript前端vue.jskeep-alive

Keep-alive 是什麼?以下這篇文章帶大家聊聊對vue內建元件keep-alive的理解,希望對大家有幫助!

聊聊對vue內建組件keep-alive的理解

一、Keep-alive 是什麼

keep-alivevue中的內建元件,能在元件切換過程中將狀態保留在記憶體中,防止重複渲染DOMvuejs影片教學、web前端開發

#keep-alive

keep-alive可以設定以下props屬性:

  • include
  • exclude
  • max

關於keep-alive的基本用法:

<keep-alive>
  <component :is="view"></component>
</keep-alive>

使用includesexclude

<keep-alive include="a,b">
  <component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="[&#39;a&#39;, &#39;b&#39;]">
  <component :is="view"></component>
</keep-alive>

符合先檢查元件本身的 namename components

設定了keep-alive 快取的元件,會多出兩個生命週期鉤子(activated deactivated):

  • 第一次進入元件時:beforeRouteEnterbeforeCreatecreated## > created## > created# mountedactivated ... ... > beforeRouteLeave#deactivated#再次進入元件時: beforeRouteEnter
  • activated ... ... > 

    beforeRouteLeavedeactivated

    #1 #二、使用場景

    使用原則:當我們在某些​​場景下不需要讓頁面重新載入時我們可以使用

    keepalive舉個栗子:當我們從首頁

    –>

    列表頁–>商詳頁–>再返回,這時候列表頁應該是需要keep-alive

    首頁–>列表頁–>商詳頁

    –>

    回到列表頁(需要快取)–>回到首頁(需要快取)

    –>

    再次進入列表頁(不需要快取),這時候可以按需來控制頁面的keep-alive

    在路由中設定###keepAlive###屬性判斷是否需要緩存###
    {
      path: &#39;list&#39;,
      name: &#39;itemList&#39;, // 列表页
      component (resolve) {
        require([&#39;@/pages/item/list&#39;], resolve)
     },
     meta: {
      keepAlive: true,
      title: &#39;列表页&#39;
     }
    }
    ###使用#########
    <div id="app" class=&#39;wrapper&#39;>
        <keep-alive>
            <!-- 需要缓存的视图组件 --> 
            <router-view v-if="$route.meta.keepAlive"></router-view>
         </keep-alive>
          <!-- 不需要缓存的视图组件 -->
         <router-view v-if="!$route.meta.keepAlive"></router-view>
    </div>
    ######三、原理分析############keep-alive# ##是###vue###中內建的一個元件######原始碼位置:src/core/components/keep-alive.js###
    export default {
      name: &#39;keep-alive&#39;,
      abstract: true,
    
      props: {
        include: [String, RegExp, Array],
        exclude: [String, RegExp, Array],
        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(&#39;include&#39;, val => {
          pruneCache(this, name => matches(val, name))
        })
        this.$watch(&#39;exclude&#39;, val => {
          pruneCache(this, name => !matches(val, name))
        })
      },
    
      render() {
        /* 获取默认插槽中的第一个组件节点 */
        const slot = this.$slots.default
        const vnode = getFirstComponentChild(slot)
        /* 获取该组件节点的componentOptions */
        const componentOptions = vnode && vnode.componentOptions
    
        if (componentOptions) {
          /* 获取该组件节点的名称,优先获取组件的name字段,如果name不存在则获取组件的tag */
          const name = getComponentName(componentOptions)
    
          const { include, exclude } = this
          /* 如果name不在inlcude中或者存在于exlude中则表示不缓存,直接返回vnode */
          if (
            (include && (!name || !matches(include, name))) ||
            // excluded
            (exclude && name && matches(exclude, name))
          ) {
            return vnode
          }
    
          const { cache, keys } = this
          /* 获取组件的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}` : &#39;&#39;)
            : vnode.key
         /*  拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存 */
          if (cache[key]) {
            vnode.componentInstance = cache[key].componentInstance
            // make current key freshest
            remove(keys, key)
            keys.push(key)
          }
            /* 如果没有命中缓存,则将其设置进缓存 */
            else {
            cache[key] = vnode
            keys.push(key)
            // prune oldest entry
            /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
            if (this.max && keys.length > parseInt(this.max)) {
              pruneCacheEntry(cache, keys[0], keys, this._vnode)
            }
          }
    
          vnode.data.keepAlive = true
        }
        return vnode || (slot && slot[0])
      }
    }
    ###可以看到該元件沒有## #template###,而是用了###render###,在元件渲染的時候會自動執行###render###函數#########this.cache###是一個對象,用來儲存需要快取的元件,它將以如下形式儲存:###
    this.cache = {
        &#39;key1&#39;:&#39;组件1&#39;,
        &#39;key2&#39;:&#39;组件2&#39;,
        // ...
    }
    ###在元件銷毀的時候執行###pruneCacheEntry###函數###
    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()
      }
      cache[key] = null
      remove(keys, key)
    }
    ###在### mounted###鉤子函數中觀測 ###include### 和 ###exclude### 的變化,如下:###
    mounted () {
        this.$watch(&#39;include&#39;, val => {
            pruneCache(this, name => matches(val, name))
        })
        this.$watch(&#39;exclude&#39;, val => {
            pruneCache(this, name => !matches(val, name))
        })
    }
    ###如果###include### 或###exclude## # 發生了變化,即表示定義需要快取的元件的規則或不需要快取的元件的規則發生了變化,那麼就執行###pruneCache###函數,函數如下:###
    function pruneCache (keepAliveInstance, filter) {
      const { cache, keys, _vnode } = keepAliveInstance
      for (const key in cache) {
        const cachedNode = cache[key]
        if (cachedNode) {
          const name = getComponentName(cachedNode.componentOptions)
          if (name && !filter(name)) {
            pruneCacheEntry(cache, key, keys, _vnode)
          }
        }
      }
    }
    ###在該函數內對###this.cache###物件進行遍歷,取出每一項的###name###值,用其與新的快取規則進行匹配,如果匹配不上,則表示在新的快取規則下該元件已經不需要被緩存,則呼叫###pruneCacheEntry###函數將其從###this.cache###物件剔除即可######關於###keep-alive ###最強大的快取功能是在###render###函數中實作######先取得元件的###key###值:###
    const key = vnode.key == null? 
    componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : &#39;&#39;)
    : vnode.key
    ###拿到# ##key###值後去###this.cache###物件中去尋找是否有該值,如果有則表示該元件有緩存,即命中緩存,如下:###
    /* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */
    if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance
        /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */
        remove(keys, key)
        keys.push(key)
    }

    直接从缓存中拿 vnodekey的顺序,将其从原来的地方删掉并重新放在this.keys中最后一个

    this.cache对象中没有该key值的情况,如下:

    /* 如果没有命中缓存,则将其设置进缓存 */
    else {
        cache[key] = vnode
        keys.push(key)
        /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */
        if (this.max && keys.length > parseInt(this.max)) {
            pruneCacheEntry(cache, keys[0], keys, this._vnode)
        }
    }

    表明该组件还没有被缓存过,则以该组件的key为键,组件vnode为值,将其存入this.cache中,并且把key存入this.keys

    此时再判断this.keys中缓存组件的数量是否超过了设置的最大缓存数量值this.max,如果超过了,则把第一个缓存组件删掉

    四、思考题:缓存后如何获取数据

    解决方案可以有以下两种:

    • beforeRouteEnter
    • actived

    beforeRouteEnter

    每次组件渲染的时候,都会执行beforeRouteEnter

    beforeRouteEnter(to, from, next){
        next(vm=>{
            console.log(vm)
            // 每次进入路由执行
            vm.getData()  // 获取数据
        })
    },

    actived

    keep-alive缓存的组件被激活的时候,都会执行actived钩子

    activated(){
       this.getData() // 获取数据
    },

    注意:服务器端渲染期间avtived不被调用

    (学习视频分享:vuejs入门教程编程基础视频

    以上是聊聊對vue內建組件keep-alive的理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金社区。如有侵權,請聯絡admin@php.cn刪除
Vue.js vs. React:哪個框架適合您?Vue.js vs. React:哪個框架適合您?May 01, 2025 am 12:21 AM

Vue.js適合快速開發和小型項目,而React更適合大型和復雜的項目。 1.Vue.js簡單易學,適用於快速開發和小型項目。 2.React功能強大,適合大型和復雜的項目。 3.Vue.js的漸進式特性適合逐步引入功能。 4.React的組件化和虛擬DOM在處理複雜UI和數據密集型應用時表現出色。

VUE.JS與React:JavaScript框架的比較分析VUE.JS與React:JavaScript框架的比較分析Apr 30, 2025 am 12:10 AM

Vue.js和React各有優缺點,選擇時需綜合考慮團隊技能、項目規模和性能需求。 1)Vue.js適合快速開發和小型項目,學習曲線低,但深層嵌套對象可能導致性能問題。 2)React適用於大型和復雜應用,生態系統豐富,但頻繁更新可能導致性能瓶頸。

vue.js vs.反應:用例和應用程序vue.js vs.反應:用例和應用程序Apr 29, 2025 am 12:36 AM

Vue.js適合小型到中型項目,React適合大型項目和復雜應用場景。 1)Vue.js易於上手,適用於快速原型開發和小型應用。 2)React在處理複雜狀態管理和性能優化方面更有優勢,適合大型項目。

VUE.JS與React:比較性能和效率VUE.JS與React:比較性能和效率Apr 28, 2025 am 12:12 AM

Vue.js和React各有優勢:Vue.js適用於小型應用和快速開發,React適合大型應用和復雜狀態管理。 1.Vue.js通過響應式系統實現自動更新,適用於小型應用。 2.React使用虛擬DOM和diff算法,適合大型和復雜應用。選擇框架時需考慮項目需求和團隊技術棧。

vue.js vs.反應:社區,生態系統和支持vue.js vs.反應:社區,生態系統和支持Apr 27, 2025 am 12:24 AM

Vue.js和React各有優勢,選擇應基於項目需求和團隊技術棧。 1.Vue.js社區友好,提供豐富學習資源,生態系統包括VueRouter等官方工具,支持由官方團隊和社區提供。 2.React社區偏向企業應用,生態系統強大,支持由Facebook及其社區提供,更新頻繁。

React和Netflix:探索關係React和Netflix:探索關係Apr 26, 2025 am 12:11 AM

Netflix使用React來提升用戶體驗。 1)React的組件化特性幫助Netflix將復雜UI拆分成可管理模塊。 2)虛擬DOM優化了UI更新,提高了性能。 3)結合Redux和GraphQL,Netflix高效管理應用狀態和數據流動。

vue.js vs.後端框架:澄清區別vue.js vs.後端框架:澄清區別Apr 25, 2025 am 12:05 AM

Vue.js是前端框架,後端框架用於處理服務器端邏輯。 1)Vue.js專注於構建用戶界面,通過組件化和響應式數據綁定簡化開發。 2)後端框架如Express、Django處理HTTP請求、數據庫操作和業務邏輯,運行在服務器上。

vue.js和前端堆棧:了解連接vue.js和前端堆棧:了解連接Apr 24, 2025 am 12:19 AM

Vue.js與前端技術棧緊密集成,提升開發效率和用戶體驗。 1)構建工具:與Webpack、Rollup集成,實現模塊化開發。 2)狀態管理:與Vuex集成,管理複雜應用狀態。 3)路由:與VueRouter集成,實現單頁面應用路由。 4)CSS預處理器:支持Sass、Less,提升樣式開發效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)