What is keep-alive?

concept

When switching between components, components can be wrapped with keep-alive to keep them in state to avoid performance problems caused by repeated rerendering.

<! Basic usage --><keep-alive>
  <component :is="view"></component>
</keep-alive>
Copy the code

Keep-alive is used to cache components and avoid repeated rendering of components.

Basic attributes

The property name type role
include String or regular expression Only components with matching names are cached
exclude String or regular expression Any component with a matching name will not be cached
max digital Maximum number of component instances can be cached
<keep-alive :max=10 :include="['a', 'b']">
    <component :is="view"></component>
</keep-alive>
Copy the code

Principle (LRU algorithm)

What is LRU?

LRU: Least Recently Used. It is mainly Used for caching.

  • The most recently used or accessed data is placed first;
  • Whenever a cache hit (that is, cached data is accessed), the data is moved to the header;
  • When the number of caches reaches the maximum, the least recently accessed data is removed.

The key point

  • One maximum capacity, two apis;
    • Max: Max in keep-alive;
    • Get: cache data is obtained
    • Put: Adds data to the cache
  • Caching is one of the most important principles, fast, so its operation is o(1) time complexity;
  • The last accessed element is in the first;

The algorithm implements LRU

Train of thought

// Set the cache capacity Max /* Cache capacity */
LRUCache cache = new LRUCache(2);
// The recently used ones go to the head of the queue, the ones that have not been used for a long time go to the bottom of the queue;
cache.put(key1,value1);
// cache: [(key1,value1)]
cache.put(key2,value2);
// cache: [(key2,value2), (key1,value1)]
cache.get(key1) / / return value1
[(key1,value1), (key2,value2)]
cache.put(key3,value3);
[(key3,value3), (key1,value1)]
cache.get(key2)  // -1 can't get this value
cache.put(key1,value4); 
[(key1,value4), (key3,value3)] [(key1,value4), (key3,value3)
Copy the code

How do you do that?

To achieve fast and orderly search, how to achieve it? The map? Map is unordered and does not meet requirements. You can use:

Two-way linked list + hash list way to achieve

In the code

// Define the node class
class Node {
    constructor(pre, next, value, key){
        this.pre = pre;
        this.next = next;
        this.value = value;
        this.key = key; }}// Define a bidirectional list
class DoubleList {
    constructor(head, tail){
        this.head = head;
        this.tail = tail; }}class LRUCache {
    // Constructor, passing in the cache capacity
    constructor(max){
        this.max = max;
        this.map = new Map(a);let node = new Node(null.null.null.null);
        this.doubleList = new DoubleList(node, node);
    }
    
    /** * returns -1 if no value exists, and moves this object to tail *@param {*} Key the key value * /
    get(key){
        let node = this.map.get(key)
        if(! node){return -1;
        }else{
            this.moveNode2Tail(key, node);
            returnnode.value; }}/** * insert cache * 1. No corresponding key exists, add to tail * 2. There is a corresponding key value, update this key value corresponding to value and mention tail * 3. If the capacity exceeds, remove the header data *@param {*} * the key key values@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; }}// Move the node to the tail
    moveNode2Tail(key,node){   
        if(! node.next){return;
        }
        // Delete a node
        node.pre.next = node.next;
        node.next.pre = node.pre;
        this.map.delete(key)
        // Add a tail node
        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); }}Copy the code