最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

keep-alive組件的作用與原理分析

 更新時間:2024年05月08日 10:52:47   作者:heiyay  
這篇文章主要介紹了keep-alive組件的作用與原理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

什么是keep-alive

“keep-alive” 是 Vue.js 中的一個特殊組件,用于緩存組件的狀態(tài),以提高應(yīng)用性能。

在 Vue.js 中,組件通常是動態(tài)創(chuàng)建和銷毀的,當(dāng)切換到另一個頁面或組件時,之前的組件會被銷毀,再次進(jìn)入時會重新創(chuàng)建和初始化。

這樣可能導(dǎo)致組件的狀態(tài)丟失,需要重新初始化,增加了資源的消耗。

組件解決了這個問題,它可以將組件緩存起來,而不是銷毀,使得組件在再次進(jìn)入時保持之前的狀態(tài),以及避免重復(fù)的創(chuàng)建和初始化過程。

這樣可以大幅度提高組件的加載速度和性能。

keep-alive的作用

<keep-alive> 的作用是在 Vue.js 應(yīng)用中緩存組件的狀態(tài),以提高應(yīng)用性能和用戶體驗。

它可以將組件暫時保存在內(nèi)存中,而不是每次都重新創(chuàng)建和初始化組件。

主要的作用有以下幾點:

  • 組件狀態(tài)保持:通過使用 <keep-alive>,在組件被切換時,其狀態(tài)會被保留。這意味著組件內(nèi)部的數(shù)據(jù)、狀態(tài)以及一些計算結(jié)果都會被緩存,不會因為組件的銷毀而丟失。當(dāng)再次進(jìn)入該組件時,它會恢復(fù)到之前的狀態(tài),而不需要重新初始化。這對于用戶在不同頁面或組件間切換時提供了更流暢的體驗。
  • 減少資源消耗:如果沒有使用 <keep-alive>,每次切換到一個組件時,都需要重新創(chuàng)建和初始化組件。對于復(fù)雜的組件,這可能會導(dǎo)致不必要的資源消耗,例如重新加載數(shù)據(jù)、執(zhí)行復(fù)雜的計算等。而使用 <keep-alive>,組件被緩存起來,下次再次進(jìn)入時直接從緩存中恢復(fù),避免了重復(fù)的初始化過程,大大減少了資源消耗。
  • 優(yōu)化性能:由于避免了重復(fù)的創(chuàng)建和初始化過程,使用 <keep-alive> 可以顯著提高組件的加載速度,加快頁面響應(yīng)時間,從而提供更好的用戶體驗。

需要注意的是,<keep-alive> 并不是適用于所有組件的,特別是對于一些動態(tài)變化的組件,如果希望每次進(jìn)入時都重新初始化,或者希望釋放組件占用的資源,就不應(yīng)該使用 <keep-alive>

要使用 <keep-alive>,只需將需要緩存的組件包裹在 <keep-alive> 標(biāo)簽中即可,Vue.js 會自動管理緩存和組件的生命周期。這是一個簡單但強(qiáng)大的功能,可在合適的場景下大幅度提升應(yīng)用性能。

原理

<keep-alive> 的原理主要涉及兩個方面:組件緩存和生命周期的管理。

組件緩存

  • 當(dāng)一個組件被包裹在 <keep-alive> 標(biāo)簽中時,Vue.js 會將該組件的實例緩存起來,而不是銷毀它。
  • 組件的緩存是通過一個名為 cache 的對象來管理的,該對象會保存被緩存的組件實例。
  • 當(dāng)切換到一個被緩存的組件時,Vue.js 首先檢查 cache 對象中是否已經(jīng)有該組件的緩存實例。如果有,就直接從緩存中取出該實例;如果沒有,就創(chuàng)建一個新的組件實例并將其緩存起來。

生命周期的管理

  • 在切換到一個被緩存的組件時,組件的生命周期鉤子函數(shù)并不會被觸發(fā),而是會觸發(fā) <keep-alive> 自己的生命周期鉤子函數(shù)。
  • <keep-alive> 組件有兩個主要的生命周期鉤子函數(shù):created 和 destroyed。
  • 在組件第一次被緩存時,created 鉤子函數(shù)會被觸發(fā),表示 <keep-alive> 組件已經(jīng)創(chuàng)建,此時會創(chuàng)建被緩存組件的實例并將其緩存起來。
  • 在切換到其他組件時,destroyed 鉤子函數(shù)會被觸發(fā),表示 <keep-alive> 組件將被銷毀,此時會銷毀所有緩存的組件實例。

需要注意的是,被包裹在 <keep-alive> 標(biāo)簽中的組件,必須具有唯一的標(biāo)識,否則會導(dǎo)致緩存沖突。

默認(rèn)情況下,Vue.js 使用組件的名稱作為緩存的標(biāo)識,但也可以通過 key 屬性來指定唯一的標(biāo)識。

使用 <keep-alive> 時,要注意以下幾點:

  • 不是所有組件都適合使用 <keep-alive>,對于一些動態(tài)變化的組件,或者需要每次進(jìn)入時重新初始化的組件,應(yīng)該避免使用 <keep-alive>。
  • 緩存的組件仍然會觸發(fā) activated 和 deactivated 生命周期鉤子函數(shù),可以在這兩個鉤子函數(shù)中處理一些特定的邏輯。
  • 如果被緩存的組件包含了一些依賴于外部狀態(tài)(如路由參數(shù)、Vuex 狀態(tài)等)的邏輯,需要特別注意在重新進(jìn)入組件時是否需要重新更新這些狀態(tài)。

總的來說,<keep-alive> 提供了一種簡單且強(qiáng)大的機(jī)制來優(yōu)化 Vue.js 應(yīng)用的性能,特別是在頻繁切換組件的場景下。

使用

當(dāng)您使用 <keep-alive> 組件時,通常需要將需要緩存的組件包裹在 <keep-alive> 標(biāo)簽中,并為每個被緩存的組件設(shè)置一個唯一的 key 屬性,以確保緩存的正確性。

下面是一個使用 <keep-alive> 組件的示例:

假設(shè)我們有兩個組件,一個是用于顯示用戶信息的組件 <UserProfile>,另一個是用于顯示用戶訂單信息的組件 <UserOrders>。

我們希望在用戶切換到 <UserProfile> 組件時,保持該組件的狀態(tài),并且在用戶切換到 <UserOrders> 組件后再切換回來時,不重新初始化 <UserProfile> 組件。

<template>
  <div>
    <keep-alive>
      <!-- 使用 key 屬性確保組件的正確緩存 -->
      <component :is="currentComponent" :key="currentComponent" />
    </keep-alive>

    <button @click="showUserProfile">Show User Profile</button>
    <button @click="showUserOrders">Show User Orders</button>
  </div>
</template>

<script>
import UserProfile from './UserProfile.vue';
import UserOrders from './UserOrders.vue';

export default {
  components: {
    UserProfile,
    UserOrders,
  },
  data() {
    return {
      currentComponent: 'UserProfile', // 初始顯示用戶信息組件
    };
  },
  methods: {
    showUserProfile() {
      this.currentComponent = 'UserProfile';
    },
    showUserOrders() {
      this.currentComponent = 'UserOrders';
    },
  },
};
</script>

在上面的示例中,使用了動態(tài)組件 <component :is="currentComponent"> 來動態(tài)地切換顯示 <UserProfile><UserOrders> 組件。

同時,將 <keep-alive> 標(biāo)簽包裹在動態(tài)組件外部,這樣 <keep-alive> 會緩存當(dāng)前被顯示的組件。

在切換組件時,使用 key 屬性來確保緩存的正確性。當(dāng)切換到不同的組件時,key 的值會變化,這會觸發(fā) <keep-alive> 的重新緩存行為。

注意,key 屬性應(yīng)該是唯一的,以確保每個組件都能被正確地緩存。在實際應(yīng)用中,可能需要根據(jù)組件的具體情況設(shè)置不同的 key 值。

理解源碼

<keep-alive> 組件的源碼相對比較復(fù)雜,涉及到 Vue.js 的虛擬 DOM、組件實例管理、生命周期管理等方面。

下面簡要介紹 <keep-alive> 的關(guān)鍵源碼部分,以便了解其基本原理。

在 Vue.js 的源碼中,<keep-alive> 組件是由一個特殊的內(nèi)置組件 KeepAlive 實現(xiàn)的。它的主要作用是處理組件的緩存和管理緩存組件的生命周期。

組件的緩存實現(xiàn)

  • KeepAlive 組件內(nèi)部維護(hù)了一個名為 cache 的對象,用于存儲緩存的組件實例。
  • 在切換到一個被緩存的組件時,KeepAlive 組件首先會檢查 cache 對象,是否已經(jīng)有該組件的緩存實例。
  • 如果緩存中有該組件實例,KeepAlive 直接返回緩存的組件實例;如果沒有,KeepAlive 會創(chuàng)建一個新的組件實例,并將其緩存起來。

組件生命周期的管理

  • KeepAlive 組件有兩個重要的生命周期鉤子函數(shù):createddestroyed
  • created 鉤子函數(shù)中,KeepAlive 會監(jiān)聽父組件的 includeexclude 屬性的變化,以決定是否緩存某個組件。
  • 在切換到被緩存組件時,KeepAlive 會觸發(fā) activated 生命周期鉤子函數(shù),并從 cache 中取出對應(yīng)的緩存組件實例。如果沒有緩存實例,會觸發(fā)被緩存組件的 created 生命周期。
  • 在切換到其他組件時,KeepAlive 會觸發(fā) deactivated 生命周期鉤子函數(shù),并將當(dāng)前緩存的組件實例暫時從 cache 中移除。如果需要緩存,則緩存的組件實例并不會被銷毀。

組件銷毀時的處理

  • destroyed 鉤子函數(shù)中,KeepAlive 會銷毀所有緩存的組件實例,并清空 cache 對象。

如果想深入了解 <keep-alive> 的源碼實現(xiàn),可以查閱 Vue.js 的 GitHub 倉庫并瀏覽相關(guān)代碼 keep-alive源碼。

這個是從github拿的源碼,有興趣可以研究一下。

import { isRegExp, isArray, remove } from 'shared/util'
import { getFirstComponentChild } from 'core/vdom/helpers/index'
import type VNode from 'core/vdom/vnode'
import type { VNodeComponentOptions } from 'types/vnode'
import type { Component } from 'types/component'
import { getComponentName } from '../vdom/create-component'

type CacheEntry = {
  name?: string
  tag?: string
  componentInstance?: Component
}

type CacheEntryMap = Record<string, CacheEntry | null>

function _getComponentName(opts?: VNodeComponentOptions): string | null {
  return opts && (getComponentName(opts.Ctor.options as any) || opts.tag)
}

function matches(
  pattern: string | RegExp | Array<string>,
  name: string
): boolean {
  if (isArray(pattern)) {
    return pattern.indexOf(name) > -1
  } else if (typeof pattern === 'string') {
    return pattern.split(',').indexOf(name) > -1
  } else if (isRegExp(pattern)) {
    return pattern.test(name)
  }
  /* istanbul ignore next */
  return false
}

function pruneCache(
  keepAliveInstance: { cache: CacheEntryMap; keys: string[]; _vnode: VNode },
  filter: Function
) {
  const { cache, keys, _vnode } = keepAliveInstance
  for (const key in cache) {
    const entry = cache[key]
    if (entry) {
      const name = entry.name
      if (name && !filter(name)) {
        pruneCacheEntry(cache, key, keys, _vnode)
      }
    }
  }
}

function pruneCacheEntry(
  cache: CacheEntryMap,
  key: string,
  keys: Array<string>,
  current?: VNode
) {
  const entry = cache[key]
  if (entry && (!current || entry.tag !== current.tag)) {
    // @ts-expect-error can be undefined
    entry.componentInstance.$destroy()
  }
  cache[key] = null
  remove(keys, key)
}

const patternTypes: Array<Function> = [String, RegExp, Array]

// TODO defineComponent
export default {
  name: 'keep-alive',
  abstract: true,

  props: {
    include: patternTypes,
    exclude: patternTypes,
    max: [String, Number]
  },

  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
      }
    }
  },

  created() {
    this.cache = Object.create(null)
    this.keys = []
  },

  destroyed() {
    for (const key in this.cache) {
      pruneCacheEntry(this.cache, key, this.keys)
    }
  },

  mounted() {
    this.cacheVNode()
    this.$watch('include', val => {
      pruneCache(this, name => matches(val, name))
    })
    this.$watch('exclude', val => {
      pruneCache(this, name => !matches(val, name))
    })
  },

  updated() {
    this.cacheVNode()
  },

  render() {
    const slot = this.$slots.default
    const vnode = getFirstComponentChild(slot)
    const componentOptions = vnode && vnode.componentOptions
    if (componentOptions) {
      // check pattern
      const name = _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
      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
      if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance
        // make current key freshest
        remove(keys, key)
        keys.push(key)
      } else {
        // delay setting the cache until update
        this.vnodeToCache = vnode
        this.keyToCache = key
      }

      // @ts-expect-error can vnode.data can be undefined
      vnode.data.keepAlive = true
    }
    return vnode || (slot && slot[0])
  }
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue中使用stylus報錯的解決

    Vue中使用stylus報錯的解決

    如果你也和我一樣,按照正常的流程下載并且配置了stylus,但是依舊報錯,也許這篇文章就是你的菜,一起來看看吧
    2022-08-08
  • Vue封裝的標(biāo)準(zhǔn)漏斗圖教程

    Vue封裝的標(biāo)準(zhǔn)漏斗圖教程

    文章展示了基于Vue封裝的標(biāo)準(zhǔn)漏斗圖的代碼,包括權(quán)重算法、滾輪監(jiān)聽和點擊示例功能,旨在提供實用的圖表展示技巧
    2025-02-02
  • vue多層嵌套路由實例分析

    vue多層嵌套路由實例分析

    這篇文章主要介紹了vue多層嵌套路由,結(jié)合實例形式分析了vue.js多層嵌套路由的概念、原理及相關(guān)操作技巧,需要的朋友可以參考下
    2019-03-03
  • Bpmn.js?自定義描述文件使用說明

    Bpmn.js?自定義描述文件使用說明

    這篇文章主要為大家介紹了Bpmn.js?自定義描述文件使用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Vue中的移動端事件插件vue-touch詳解

    Vue中的移動端事件插件vue-touch詳解

    文章介紹了vue-touch庫,它提供了單擊、雙擊、長按、縮放等手勢事件,通過npm安裝后,開發(fā)者可以在Vue項目中使用這些手勢事件,文章還分享了使用vue-touch的基本方法,并鼓勵讀者參考和支持腳本之家
    2026-02-02
  • Vue filter格式化時間戳?xí)r間成標(biāo)準(zhǔn)日期格式的方法

    Vue filter格式化時間戳?xí)r間成標(biāo)準(zhǔn)日期格式的方法

    今天小編就為大家分享一篇Vue filter格式化時間戳?xí)r間成標(biāo)準(zhǔn)日期格式的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • django+vue項目搭建實現(xiàn)前后端通信

    django+vue項目搭建實現(xiàn)前后端通信

    本文主要介紹了django+vue項目搭建實現(xiàn)前后端通信,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • vue?實現(xiàn)彈窗關(guān)閉后刷新效果

    vue?實現(xiàn)彈窗關(guān)閉后刷新效果

    這篇文章主要介紹了vue?實現(xiàn)彈窗關(guān)閉后刷新效果,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue cli 3.0通用打包配置代碼,不分一二級目錄

    vue cli 3.0通用打包配置代碼,不分一二級目錄

    這篇文章主要介紹了vue cli 3.0通用打包配置代碼,不分一二級目錄,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 基于vue監(jiān)聽滾動事件實現(xiàn)錨點鏈接平滑滾動的方法

    基于vue監(jiān)聽滾動事件實現(xiàn)錨點鏈接平滑滾動的方法

    本篇文章主要介紹了基于vue監(jiān)聽滾動事件實現(xiàn)錨點鏈接平滑滾動的方法,非常具有實用價值,有興趣的可以了解一下
    2018-01-01

最新評論

洛川县| 南丹县| 连平县| 咸宁市| 抚松县| 新龙县| 蒙自县| 宝应县| 九寨沟县| 新宾| 分宜县| 黄陵县| 衡阳县| 镇江市| 文水县| 缙云县| 许昌市| 乐亭县| 拜泉县| 常熟市| 德化县| 佛山市| 湘阴县| 阿鲁科尔沁旗| 惠来县| 咸阳市| 南投县| 盐山县| 大庆市| 元阳县| 常山县| 白河县| 友谊县| 兴安县| 石首市| 瑞金市| 安岳县| 余庆县| 茶陵县| 太保市| 安徽省|