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

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

 更新時(shí)間:2021年05月31日 17:30:08   作者:Cc沖沖沖  
LRU算法全稱為least recently use 最近最少使用,核心思路是最近被訪問的以后被訪問的概率會(huì)變高,那么可以把之前沒被訪問的進(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 的過程中
  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)聽緩存(include)/不緩存(exclude)組件的變化
    // 在變化時(shí),重新調(diào)整 cache
    // pruneCache:遍歷 cache,如果緩存的節(jié)點(diǎn)名稱與傳入的規(guī)則沒有匹配上的話,就把這個(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)整,
      // 沒有則放入(長度超過 max,則淘汰最近沒有訪問的)
      // --------------------------------------------------
      // 如果命中緩存,則從緩存中獲取 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);
      }
      // 如果沒有命中緩存,就把 vnode 放進(jìn)緩存
      else {
        cache[key] = vnode;
        keys.push(key);
        // prune oldest entry
        // 如果配置了 max 并且緩存的長度超過了 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ì)是類似隊(duì)列 put實(shí)現(xiàn)思路 1 是否存在,存在就先刪除,再添加到隊(duì)頭 2 不存在,容量是否滿了,刪除最后一個(gè)隊(duì)尾,再添加隊(duì)頭 get實(shí)現(xiàn)思路: 1.有就返回,同時(shí)插入隊(duì)頭 2.沒有返回-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 {
      //不存在,容量是否滿了
      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
    }
    //訪問了就需要放在隊(duì)頭
    this.put(key, val)
    return val
  }
}

另一種

//定義節(jié)點(diǎn)類
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.超出容量的話,去掉頭部數(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)文章

  • Vue2實(shí)現(xiàn)子組件修改父組件值的方法小結(jié)

    Vue2實(shí)現(xiàn)子組件修改父組件值的方法小結(jié)

    在 Vue 2 中,子組件不能直接修改父組件的值,因?yàn)?nbsp;Vue 遵循單向數(shù)據(jù)流的原則,為了實(shí)現(xiàn)子組件修改父組件的數(shù)據(jù),本文給大家介紹了Vue2實(shí)現(xiàn)子組件修改父組件值的四種方法,并通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • 在Vue中使用Avue、配置過程及實(shí)際應(yīng)用小結(jié)

    在Vue中使用Avue、配置過程及實(shí)際應(yīng)用小結(jié)

    在項(xiàng)目中遇到通過點(diǎn)擊加號(hào)實(shí)現(xiàn)輸入框的增加、以及對(duì)該輸入框的輸入內(nèi)容進(jìn)行驗(yàn)證,通過這些誘導(dǎo)因素創(chuàng)作的這篇文章,本文重點(diǎn)給大家介紹在Vue中使用Avue、配置過程以及實(shí)際應(yīng)用,需要的朋友可以參考下
    2022-10-10
  • Element?UI表單驗(yàn)證規(guī)則動(dòng)態(tài)失效問題的解決辦法

    Element?UI表單驗(yàn)證規(guī)則動(dòng)態(tài)失效問題的解決辦法

    這篇文章主要給大家介紹了關(guān)于Element?UI表單驗(yàn)證規(guī)則動(dòng)態(tài)失效問題的解決辦法,Element UI提供了強(qiáng)大的表單驗(yàn)證功能,可以輕松地對(duì)表單進(jìn)行驗(yàn)證,需要的朋友可以參考下
    2023-09-09
  • 一文探索Vue中組件和插件使用細(xì)節(jié)與差異

    一文探索Vue中組件和插件使用細(xì)節(jié)與差異

    Vue組件和插件是Vue生態(tài)系統(tǒng)中的兩種重要概念,它們分別服務(wù)于不同的目的,但都極大地豐富了Vue的功能性和可擴(kuò)展性,下面我們就來看看二者的用法以及區(qū)別吧
    2024-03-03
  • vue3.0中使用element UI表單遍歷校驗(yàn)問題解決

    vue3.0中使用element UI表單遍歷校驗(yàn)問題解決

    本文主要介紹了vue3.0中使用element UI表單遍歷校驗(yàn)問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • vue中this.$router.go(-1)失效(路由改變了,界面未刷新)

    vue中this.$router.go(-1)失效(路由改變了,界面未刷新)

    本文主要介紹了vue中this.$router.go(-1)失效(路由改變了,界面未刷新),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • antd Select下拉菜單動(dòng)態(tài)添加option里的內(nèi)容操作

    antd Select下拉菜單動(dòng)態(tài)添加option里的內(nèi)容操作

    這篇文章主要介紹了antd Select下拉菜單動(dòng)態(tài)添加option里的內(nèi)容操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue.js使用v-model實(shí)現(xiàn)父子組件間的雙向通信示例

    vue.js使用v-model實(shí)現(xiàn)父子組件間的雙向通信示例

    這篇文章主要介紹了vue.js使用v-model實(shí)現(xiàn)父子組件間的雙向通信,結(jié)合實(shí)例形式分析了vue.js基于v-model父子組件間的雙向通信的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2020-02-02
  • uni-app項(xiàng)目中引入Vant?UI組件庫完美避坑指南(純凈版)

    uni-app項(xiàng)目中引入Vant?UI組件庫完美避坑指南(純凈版)

    網(wǎng)上百度uniapp使用vant時(shí),很多答案都是在根路徑下創(chuàng)建文件夾,而且都是基于小程序環(huán)境的,其實(shí)uniapp可以直接使用的,這篇文章主要給大家介紹了關(guān)于uni-app項(xiàng)目中引入Vant?UI組件庫完美避坑指南的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • 一篇文章帶你搞懂Vue虛擬Dom與diff算法

    一篇文章帶你搞懂Vue虛擬Dom與diff算法

    這篇文章主要給大家介紹了關(guān)于Vue虛擬Dom與diff算法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評(píng)論

延津县| 东阳市| 中宁县| 塔城市| 满洲里市| 浙江省| 玉树县| 东明县| 屏东县| 南江县| 彝良县| 鄂尔多斯市| 凤庆县| 湖北省| 吉木萨尔县| 柘荣县| 中方县| 蒲城县| 临江市| 响水县| 寿宁县| 乌兰县| 平原县| 汶上县| 灵宝市| 乐陵市| 大荔县| 莱州市| 左云县| 民丰县| 罗平县| 定结县| 黄平县| 蒙阴县| 南华县| 新化县| 固安县| 临泽县| 翁源县| 荣昌县| 涿州市|