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

LRU算法在Vue內(nèi)置組件keep-alive中的使用

 更新時間:2021年05月31日 17:30:08   作者:Cc沖沖沖  
LRU算法全稱為least recently use 最近最少使用,核心思路是最近被訪問的以后被訪問的概率會變高,那么可以把之前沒被訪問的進(jìn)行刪除,維持一個穩(wěn)定的最大容量值,從而不會導(dǎo)致內(nèi)存溢出。

vue的keep-alive內(nèi)置組件的使用也是使用了改算法,源碼如下:

export default {
  name: "keep-alive",
  // 抽象組件屬性 ,它在組件實例建立父子關(guān)系的時候會被忽略,發(fā)生在 initLifecycle 的過程中
  abstract: true, 
  props: {
    // 被緩存組件
    include: patternTypes, 
    // 不被緩存組件
    exclude: patternTypes,
    // 指定緩存大小
    max: [String, Number] 
  },
  created() {
    // 初始化用于存儲緩存的 cache 對象
    this.cache = Object.create(null);
    // 初始化用于存儲VNode key值的 keys 數(shù)組
    this.keys = []; 
  },
  destroyed() {
    for (const key in this.cache) {
      // 刪除所有緩存
      pruneCacheEntry(this.cache, key, this.keys);
    }
  },
  mounted() {
    // 監(jiān)聽緩存(include)/不緩存(exclude)組件的變化
    // 在變化時,重新調(diào)整 cache
    // pruneCache:遍歷 cache,如果緩存的節(jié)點名稱與傳入的規(guī)則沒有匹配上的話,就把這個節(jié)點從緩存中移除
    this.$watch("include", val => {
      pruneCache(this, name => matches(val, name));
    });
    this.$watch("exclude", val => {
      pruneCache(this, name => !matches(val, name));
    });
  },
  render() {
    // 獲取第一個子元素的 vnode
    const slot = this.$slots.default;
    const vnode: VNode = getFirstComponentChild(slot);
    const componentOptions: ?VNodeComponentOptions =
      vnode && vnode.componentOptions;
    if (componentOptions) {
      // name 不在 inlcude 中或者在 exlude 中則直接返回 vnode,否則繼續(xù)進(jìn)行下一步
      // check pattern
      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;
      // 獲取鍵,優(yōu)先獲取組件的 name 字段,否則是組件的 tag
      const key: ?string =
        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;
        
      // --------------------------------------------------
      // 下面就是 LRU 算法了,
      // 如果在緩存里有則調(diào)整,
      // 沒有則放入(長度超過 max,則淘汰最近沒有訪問的)
      // --------------------------------------------------
      // 如果命中緩存,則從緩存中獲取 vnode 的組件實例,并且調(diào)整 key 的順序放入 keys 數(shù)組的末尾
      if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance;
        // make current key freshest
        remove(keys, key);
        keys.push(key);
      }
      // 如果沒有命中緩存,就把 vnode 放進(jìn)緩存
      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);
        }
      }
      
      // keepAlive標(biāo)記位
      vnode.data.keepAlive = true;
    }
    return vnode || (slot && slot[0]);
  }
};

// 移除 key 緩存
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)
}

// remove 方法(shared/util.js)
/**
 * Remove an item from an array.
 */
export function remove (arr: Array<any>, item: any): Array<any> | void {
  if (arr.length) {
    const index = arr.indexOf(item)
    if (index > -1) {
      return arr.splice(index, 1)
    }
  }
}

實現(xiàn)一個自己的LRU算法

lru算法 的核心api(put get)和一個size最大容器值,本質(zhì)是類似隊列 put實現(xiàn)思路 1 是否存在,存在就先刪除,再添加到隊頭 2 不存在,容量是否滿了,刪除最后一個隊尾,再添加隊頭 get實現(xiàn)思路: 1.有就返回,同時插入隊頭 2.沒有返回-1 時間復(fù)雜度O(1)

class LRU {
  constructor(size) {
    this.cache = new Map()
    this.size = size
  }
  put (key, val) {
    //存在
    if (this.cache.has(key)) {
      //刪除
      this.cache.delete(key)
    } else {
      //不存在,容量是否滿了
      if (this.size === this.cache.size) {
        //刪除最后一個
        this.cache.delete(this.cache.keys().next().value) //拿到隊尾的元素
      }
    }
    //插在隊頭
    this.cache.set(key, val)
  }
  get (key) {
    let val = this.cache.get(key)
    if (!val) {
      return -1
    }
    //訪問了就需要放在隊頭
    this.put(key, val)
    return val
  }
}

另一種

//定義節(jié)點類
class Node {
    constructor(pre, next, value, key){
        this.pre = pre;
        this.next = next;
        this.value = value;
        this.key = key;
    }
}

//定義雙向鏈表
class DoubleList {
    constructor(head, tail){
        this.head = head;
        this.tail = tail;
    }
}


class LRUCache {
    //構(gòu)造函數(shù),傳入緩存容量
    constructor(max){
        this.max = max;
        this.map = new Map();
        let node = new Node(null, null, null, null);
        this.doubleList = new DoubleList(node, node);
    }
    
    /**
     * 獲取緩存值
     * 不存在返回-1,存在返回對應(yīng)value值,并將此節(jié)點移到尾巴
     * @param {*} key  key值
     */
    get(key){
        let node = this.map.get(key)
        if(!node){
            return -1;
        }else{
            this.moveNode2Tail(key, node);
            return node.value;
        }
    }

    /**
     * 插入緩存
     * 1.不存在對應(yīng)key值,加到尾巴
     * 2.存在對應(yīng)key值,更新此key值對應(yīng)value并提到尾巴
     * 3.超出容量的話,去掉頭部數(shù)據(jù)
     * @param {*} key  key值
     * @param {*} value  value
     */
    put(key, value) {
        let node = this.map.get(key);
        if(node){
            if(!node.next){
                node.value = value;
                return;
            }
            node.pre.next = node.next;
            node.next.pre = node.pre;
        }
        let newNode = new Node(null, null, value, key);
        newNode.pre = this.doubleList.tail;
        this.doubleList.tail.next = newNode;
        this.doubleList.tail = newNode;
        this.map.set(key, newNode);
        if(this.map.size > this.max){
            this.map.delete(this.doubleList.head.next.key);
            this.doubleList.head.next = this.doubleList.head.next.next;
            this.doubleList.head.next.pre = this.doubleList.head;          
        }
    }
    
    //將節(jié)點移到尾巴
    moveNode2Tail(key,node){   
        if(!node.next){
            return;
        }
        //刪除節(jié)點   
        node.pre.next = node.next;
        node.next.pre = node.pre;
        this.map.delete(key)
        //新增尾巴節(jié)點
        let newNode = new Node(null, null, node.value, key);
        newNode.pre = this.doubleList.tail;
        this.doubleList.tail.next = newNode;
        this.doubleList.tail = newNode;
        this.map.set(key, newNode);
    }
}

以上就是LRU算法在Vue內(nèi)置組件keep-alive中的使用的詳細(xì)內(nèi)容,更多關(guān)于Vue LRU算法的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 用vue 實現(xiàn)手機觸屏滑動功能

    用vue 實現(xiàn)手機觸屏滑動功能

    這篇文章主要介紹了用vue 實現(xiàn)手機觸屏滑動的功能,文中通過示例代碼給大家介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • vue-router命名視圖的使用講解

    vue-router命名視圖的使用講解

    今天小編就為大家分享一篇關(guān)于vue-router命名視圖的使用講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • VUE中攔截請求并無感知刷新token方式

    VUE中攔截請求并無感知刷新token方式

    這篇文章主要介紹了VUE中攔截請求并無感知刷新token方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 使用Vue+MySQL實現(xiàn)登錄注冊的實戰(zhàn)案例

    使用Vue+MySQL實現(xiàn)登錄注冊的實戰(zhàn)案例

    第一次用Vue+MySQL實現(xiàn)注冊登錄功能,就已經(jīng)踩了很多坑,下面這篇文章主要給大家介紹了關(guān)于使用Vue+MySQL實現(xiàn)登錄注冊案例的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • vue兩個組件間值的傳遞或修改方式

    vue兩個組件間值的傳遞或修改方式

    這篇文章主要介紹了vue兩個組件間值的傳遞或修改的實現(xiàn)代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-07-07
  • Vue使用三方工具vueUse實現(xiàn)虛擬列表

    Vue使用三方工具vueUse實現(xiàn)虛擬列表

    其實采用vueUse中的useVirtualList方法同樣可以實現(xiàn)虛擬列表,這篇文章小編就來和大家詳細(xì)介紹一下如何使用vueUse實現(xiàn)簡單的虛擬列表效果吧
    2024-04-04
  • vue實現(xiàn)購物車加減

    vue實現(xiàn)購物車加減

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)購物車加減,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • vue3動態(tài)加載對話框的方法實例

    vue3動態(tài)加載對話框的方法實例

    對話框是很常用的組件,在很多地方都會用到,下面這篇文章主要給大家介紹了關(guān)于vue3動態(tài)加載對話框的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • Vue-cli3生成的Vue項目加載Mxgraph方法示例

    Vue-cli3生成的Vue項目加載Mxgraph方法示例

    這篇文章主要介紹了Vue-cli3生成的Vue項目加載Mxgraph方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Vue頁面刷新記住頁面狀態(tài)的實現(xiàn)

    Vue頁面刷新記住頁面狀態(tài)的實現(xiàn)

    這篇文章主要介紹了Vue頁面刷新記住頁面狀態(tài)的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-12-12

最新評論