Vue 組み込みコンポーネントのキープアライブでの LRU アルゴリズムの使用

Vue 組み込みコンポーネントのキープアライブでの LRU アルゴリズムの使用

Vue の keep-alive 組み込みコンポーネントの使用でもこのアルゴリズムが使用されます。ソース コードは次のとおりです。

エクスポートデフォルト{
  名前: "キープアライブ"、
  // コンポーネントインスタンスが親子関係を確立するときに無視される抽象コンポーネントプロパティ。これは initLifecycle プロセス中に発生します。abstract: true, 
  小道具: {
    // キャッシュコンポーネントには、patternTypes、 
    // キャッシュから除外するコンポーネント: patternTypes、
    // キャッシュサイズの最大値を指定します: [文字列、数値] 
  },
  作成された() {
    // キャッシュを保存するために使用するキャッシュ オブジェクトを初期化します。this.cache = Object.create(null);
    // VNode キー値を格納するために使用するキー配列を初期化します。this.keys = []; 
  },
  破壊された() {
    for (const キー in this.cache) {
      // すべてのキャッシュを削除します pruneCacheEntry(this.cache, key, this.keys);
    }
  },
  マウント() {
    // キャッシュ(含める)/除外コンポーネントの変更をリッスンする // 変更が発生したらキャッシュを再調整する
    // pruneCache: キャッシュを走査し、キャッシュされたノード名が渡されたルールと一致しない場合は、キャッシュからノードを削除します this.$watch("include", val => {
      pruneCache(this、name => matches(val、name));
    });
    this.$watch("exclude", val => {
      pruneCache(this、name => !matches(val、name));
    });
  },
  与える() {
    // 最初の子要素のvnodeを取得します
    const スロット = this.$slots.default;
    const vnode: VNode = getFirstComponentChild(スロット);
    定数コンポーネントオプション: ?VNodeComponentOptions =
      vnode && vnode.componentOptions;
    if (コンポーネントオプション) {
      // 名前が include または exclude にない場合は、vnode を直接返し、それ以外の場合は次のステップに進みます // パターンをチェックします
      定数名: ?string = getComponentName(componentOptions);
      const { include, exclude } = this;
      もし (
        // 含まれません
        (include && (!name || !matches(include, name))) ||
        // 除外
        (exclude && name && matches(exclude, name))
      ){
        vnode を返します。
      }
      
      const { キャッシュ、キー } = this;
      // キーを取得し、最初にコンポーネントの名前フィールドを取得します。それ以外の場合はコンポーネントのタグになります。
      定数キー: ?文字列 =
        vnode.key == null
          ? // 同じコンストラクタが異なるローカルコンポーネントとして登録される可能性があります
            // cid だけでは不十分です (#3269)
            コンポーネントオプション.Ctor.cid +
            (componentOptions.tag ? `::${componentOptions.tag}` : "")
          : vnode.key;
        
      // --------------------------------------------------
      // 以下はLRUアルゴリズムです。
      // キャッシュ内にある場合は調整します。
      // そうでない場合は入れます(長さが最大値を超える場合は、最近アクセスされていないものを削除します)
      // --------------------------------------------------
      // キャッシュにヒットした場合は、キャッシュからvnodeのコンポーネントインスタンスを取得し、キーの順序をキー配列の末尾に調整します。if (cache[key]) {
        vnode.componentInstance = キャッシュ[キー].componentInstance;
        // 現在のキーを最新のものにする
        削除(キー、キー);
        keys.push(キー);
      }
      // キャッシュにヒットしない場合は、vnode をキャッシュに格納します。else {
        キャッシュ[キー] = vnode;
        keys.push(キー);
        // 最も古いエントリを削除する
        // maxが設定されていて、キャッシュの長さがthis.maxを超える場合は、キャッシュから最初のものを削除します。if (this.max && keys.length > parseInt(this.max)) {
          キャッシュエントリを削除します(キャッシュ、キー[0]、キー、this._vnode);
        }
      }
      
      // キープアライブフラグ vnode.data.keepAlive = true;
    }
    vnode || (slot && slot[0]) を返します。
  }
};

// キーキャッシュを削除する関数pruneCacheEntry(
  キャッシュ: VNodeCache、
  キー: 文字列、
  キー: 配列<文字列>,
  現在の?: VNode
){
  const キャッシュ = キャッシュ[キー]
  if (cached && (!current || cached.tag !== current.tag)) {
    キャッシュされたコンポーネントインスタンス.$destroy()
  }
  キャッシュ[キー] = null
  削除(キー、キー)
}

// メソッドを削除 (shared/util.js)
/**
 * 配列から項目を削除します。
 */
エクスポート関数remove (arr: Array<any>, item: any): Array<any> | void {
  (arr.length)の場合{
    定数インデックス = arr.indexOf(item)
    (インデックス>-1)の場合{
      arr.splice(インデックス, 1) を返す
    }
  }
}

独自のLRUアルゴリズムの実装

lru アルゴリズムのコア API (put get) と最大コンテナ値のサイズは、基本的にキュー put の実装アイデアに似ています。1. 存在する場合は、まずそれを削除してからキューの先頭に追加します。2. 存在しない場合は、容量がいっぱいかどうかに関係なく、キューの最後の末尾を削除してからキューの先頭を追加します。get の実装アイデア: 1. 存在する場合は返し、キューの先頭に挿入します。2. 存在しない場合は、-1 を返します。時間計算量 O(1)

クラスLRU {
  コンストラクタ(サイズ) {
    this.cache = 新しいマップ()
    this.size = サイズ
  }
  (キー、値) を置く {
    //存在する場合(this.cache.has(key)) {
      //削除 this.cache.delete(key)
    } それ以外 {
      // 存在しない、容量がいっぱいです if (this.size === this.cache.size) {
        //最後のものを削除します this.cache.delete(this.cache.keys().next().value) //キューの末尾の要素を取得します}
    }
    //キューの先頭に挿入 this.cache.set(key, val)
  }
  取得 (キー) {
    val = this.cache.get(キー) とします。
    もし(!val) {
      -1を返す
    }
    //アクセス後、キューの先頭に配置する必要があります this.put(key, val)
    戻り値
  }
}

別の

//ノードクラスを定義する class Node {
    コンストラクタ(前、次、値、キー){
        this.pre = pre;
        this.next = 次へ;
        this.value = 値;
        this.key = キー;
    }
}

//双方向リンクリストクラスを定義する DoubleList {
    コンストラクタ(head, tail){
        this.head = ヘッド;
        this.tail = テール;
    }
}


クラスLRUCache {
    //コンストラクタ、キャッシュ容量を渡すconstructor(max){
        this.max = 最大値;
        this.map = 新しい Map();
        ノードを新しいノード(null, null, null, null);
        this.doubleList = 新しい DoubleList(node, node);
    }
    
    /**
     * キャッシュ値を取得します * 存在しない場合は -1 を返します。存在する場合は、対応する値を返してこのノードを末尾に移動します * @param {*} key key value */
    get(キー){
        ノード = this.map.get(キー)
        if(!ノード){
            -1 を返します。
        }それ以外{
            this.moveNode2Tail(キー、ノード);
            ノード値を返します。
        }
    }

    /**
     * キャッシュを挿入 * 1. 対応するキー値が存在しない場合は末尾に追加します * 2. 対応するキー値が存在する場合は、このキー値に対応する値を更新して末尾に記述します * 3. 容量を超えた場合は、ヘッダーデータを削除します * @param {*} key キー値 * @param {*} value 値
     */
    put(キー, 値) {
        ノード = this.map.get(キー);
        if(ノード){
            if(!node.next){
                ノードの値 = 値;
                戻る;
            }
            node.pre.next = node.next;
            ノードを次のノードにリンクします。
        }
        newNode = new Node(null, null, 値, キー);
        newNode.pre = this.doubleList.tail;
        this.doubleList.tail.next = 新しいノード;
        this.doubleList.tail = newNode;
        this.map.set(キー、newNode);
        このマップのサイズがこれより大きい場合、
            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;          
        }
    }
    
    //ノードを末尾に移動する moveNode2Tail(key,node){   
        if(!node.next){
            戻る;
        }
        //ノードを削除します。node.pre.next = node.next;
        ノードを次のノードにリンクします。
        this.map.delete(キー)
        //新しい末尾ノードを追加します。let newNode = new Node(null, null, node.value, key);
        newNode.pre = this.doubleList.tail;
        this.doubleList.tail.next = 新しいノード;
        this.doubleList.tail = newNode;
        this.map.set(キー、newNode);
    }
}

上記は、Vue の組み込みコンポーネントのキープアライブにおける LRU アルゴリズムの使用に関する詳細な内容です。Vue LRU アルゴリズムの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Vue3の組み込みコンポーネントであるTeleportの使い方を詳しく説明します
  • Vue組み込みコンポーネントのキープアライブの使用例
  • vue.js組み込みコンポーネントのキープアライブコンポーネントの使用
  • Vue の新しい組み込みコンポーネントの使用方法の詳細な説明

<<:  MySQL 8.0.13 解凍版のインストールと設定方法のグラフィックチュートリアル

>>:  CentOS 8が利用可能になりました

推薦する

一定時間後にNavicatがデータベースから自動的に切断される問題の解決方法

これは、データベース サーバーが、接続が多すぎるのを避けるために、一定時間非アクティブな状態が続くと...

MySQL における Datetime と Timestamp の使用の概要

目次1. MySQL で現在の時刻を表現するにはどうすればよいでしょうか? 2. TIMESTAMP...

MySQL 8.0.12 のインストールと環境変数の設定チュートリアル (Win10 の場合)

Windows 10 プラットフォームでの MySQL のインストール、構成、起動、ログイン、環境...

JavaScript は、マウスがテーブル行を通過するときに色の識別を実装します。

この記事では、マウスがテーブルの行を通過するときにJavaScriptを使用して色ラベルを表示する方...

Vue+Openlayer をベースに geojson を動的に読み込む方法

1つ以上の機能をロードする <テンプレート> <div id="map&...

MySQL の int、char、varchar のパフォーマンスを比較する

インターネットには、真実のように見える「噂」がたくさんあります。もちろん、悪意のあるものではありませ...

CSS で要素を中央揃えにする N 通りの方法

目次序文インライン要素の中央揃えテキストを垂直に中央揃え要素を水平方向に中央揃えにするブロックレベル...

JS のオブジェクトリテラルの詳細な説明

目次序文1. オブジェクト構築にプロトタイプを設定する1.1 __proto__ の使用における特殊...

CSS3 フィルター属性の使い方の紹介

1. はじめにフロントエンドページのアニメーション効果を記述する場合、filter 属性は多かれ少な...

MySQLのパスワードを忘れた場合の対処方法

MySQL パスワードを 2 回忘れてしまいましたか?最初、私はアンインストールして再インストールす...

JavaScript クロージャの説明

目次1. クロージャとは何ですか? 1.2 クロージャのメモ化: 関数は定義された環境を記憶する1....

Vue 構成リクエストの複数サーバーソリューションの詳細な説明

1. 解決策1.1 インターフェースコンテキストパスの説明2 つのバックエンド インターフェイス サ...

Linux システムに Spring Boot アプリケーションをインストールするための詳細なチュートリアル

Unix/Linux サービスsystemd サービス操作プロセス1. JDKがインストールされたC...

JavaScript の new 演算子の原理と例の詳細な説明

新しい用途new の機能は、コンストラクターを通じてインスタンス オブジェクトを作成することです。イ...

Node.js のワーカー スレッドの詳細な理解

目次概要Node.js における CPU バウンド アプリケーションの歴史CPUを集中的に使用する操...