亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

export default {
  name: "keep-alive",
  // 抽象組件屬性 ,它在組件實(shí)例建立父子關(guān)系的時(shí)候會(huì)被忽略,發(fā)生在 initLifecycle 的過(guò)程中
  abstract: true, 
  props: {
    // 被緩存組件
    include: patternTypes, 
    // 不被緩存組件
    exclude: patternTypes,
    // 指定緩存大小
    max: [String, Number] 
  },
  created() {
    // 初始化用于存儲(chǔ)緩存的 cache 對(duì)象
    this.cache = Object.create(null);
    // 初始化用于存儲(chǔ)VNode key值的 keys 數(shù)組
    this.keys = []; 
  },
  destroyed() {
    for (const key in this.cache) {
      // 刪除所有緩存
      pruneCacheEntry(this.cache, key, this.keys);
    }
  },
  mounted() {
    // 監(jiān)聽(tīng)緩存(include)/不緩存(exclude)組件的變化
    // 在變化時(shí),重新調(diào)整 cache
    // pruneCache:遍歷 cache,如果緩存的節(jié)點(diǎn)名稱(chēng)與傳入的規(guī)則沒(méi)有匹配上的話(huà),就把這個(gè)節(jié)點(diǎn)從緩存中移除
    this.$watch("include", val => {
      pruneCache(this, name => matches(val, name));
    });
    this.$watch("exclude", val => {
      pruneCache(this, name => !matches(val, name));
    });
  },
  render() {
    // 獲取第一個(gè)子元素的 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)整,
      // 沒(méi)有則放入(長(zhǎng)度超過(guò) max,則淘汰最近沒(méi)有訪(fǎng)問(wèn)的)
      // --------------------------------------------------
      // 如果命中緩存,則從緩存中獲取 vnode 的組件實(shí)例,并且調(diào)整 key 的順序放入 keys 數(shù)組的末尾
      if (cache[key]) {
        vnode.componentInstance = cache[key].componentInstance;
        // make current key freshest
        remove(keys, key);
        keys.push(key);
      }
      // 如果沒(méi)有命中緩存,就把 vnode 放進(jìn)緩存
      else {
        cache[key] = vnode;
        keys.push(key);
        // prune oldest entry
        // 如果配置了 max 并且緩存的長(zhǎng)度超過(guò)了 this.max,還要從緩存中刪除第一個(gè)
        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)
    }
  }
}

實(shí)現(xiàn)一個(gè)自己的LRU算法

lru算法 的核心api(put get)和一個(gè)size最大容器值,本質(zhì)是類(lèi)似隊(duì)列 put實(shí)現(xiàn)思路 1 是否存在,存在就先刪除,再添加到隊(duì)頭 2 不存在,容量是否滿(mǎn)了,刪除最后一個(gè)隊(duì)尾,再添加隊(duì)頭 get實(shí)現(xiàn)思路: 1.有就返回,同時(shí)插入隊(duì)頭 2.沒(méi)有返回-1 時(shí)間復(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 {
      //不存在,容量是否滿(mǎn)了
      if (this.size === this.cache.size) {
        //刪除最后一個(gè)
        this.cache.delete(this.cache.keys().next().value) //拿到隊(duì)尾的元素
      }
    }
    //插在隊(duì)頭
    this.cache.set(key, val)
  }
  get (key) {
    let val = this.cache.get(key)
    if (!val) {
      return -1
    }
    //訪(fǎng)問(wèn)了就需要放在隊(duì)頭
    this.put(key, val)
    return val
  }
}

另一種

//定義節(jié)點(diǎn)類(lèi)
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,存在返回對(duì)應(yīng)value值,并將此節(jié)點(diǎn)移到尾巴
     * @param {*} key  key值
     */
    get(key){
        let node = this.map.get(key)
        if(!node){
            return -1;
        }else{
            this.moveNode2Tail(key, node);
            return node.value;
        }
    }

    /**
     * 插入緩存
     * 1.不存在對(duì)應(yīng)key值,加到尾巴
     * 2.存在對(duì)應(yīng)key值,更新此key值對(duì)應(yīng)value并提到尾巴
     * 3.超出容量的話(huà),去掉頭部數(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é)點(diǎn)移到尾巴
    moveNode2Tail(key,node){   
        if(!node.next){
            return;
        }
        //刪除節(jié)點(diǎn)   
        node.pre.next = node.next;
        node.next.pre = node.pre;
        this.map.delete(key)
        //新增尾巴節(jié)點(diǎn)
        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算法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 用vue 實(shí)現(xiàn)手機(jī)觸屏滑動(dòng)功能

    用vue 實(shí)現(xiàn)手機(jī)觸屏滑動(dòng)功能

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

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

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

    VUE中攔截請(qǐng)求并無(wú)感知刷新token方式

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

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

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

    vue兩個(gè)組件間值的傳遞或修改方式

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

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

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

    vue實(shí)現(xiàn)購(gòu)物車(chē)加減

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

    vue3動(dòng)態(tài)加載對(duì)話(huà)框的方法實(shí)例

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

    Vue-cli3生成的Vue項(xiàng)目加載Mxgraph方法示例

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

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

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

最新評(píng)論