# vue专题导学
# 导学
基础用法
- 命名规则
- 模板
- 单向数据流
- 事件操作
- 样式
- 生命周期
高级用法
- 双向绑定
- 组件通信
- 组件复用
- 组件封装
响应式源码分析
- 响应式源码分析
- 异步渲染队列源码分析
- Vue2.0 diff算法
- Composition Api
Vue生态以及源码分析
Vuex
- 基础使用
- 响应式源码分析 & vuex插件机制源码分析
Vue-Router
- Hash Mode 和 H5 Mode 实现源码分析
- 路由守卫过程源码分析
Nuxt
- 通过思路
- 性能优化
# 补充:LRU算法
LRU是Least Recently Used的缩写,表示最近最少使用,是一种常用的页面置换算法,选择内存中最近最久未使用的页面予以淘汰。 介绍: (opens new window)
- 地址: LRU缓存机制 (opens new window)
- 进阶: 你是否可以在O(1)时间复杂度内完成获取和删除数据操作?
- 使用场景
<keep-alive>
组件- Nuxt.js 缓存优化方案
# 实现
- 思路: 维护一个数组,提供 get 和 put 两个方法,并且限制数组元素数量(及缓存数量)
- 要求:
- get 可以标记某个元素是最新使用的,提升到第一项
- put 可以加入一个 key-value 元素,但是需要判断是否已存在,是否超出限额
实现1:数组实现
DETAILS
// 一般解法,维护一个数组,数组元素为key-value键值对对象,每次获取需要遍历数组
// 工厂函数,具有两个属性 capacity 保存限量,cache 保存缓存
let LRUCache = function(capacity){
this.capacity = capacity;
this.cache = [];
}
// 实现 get 方法
LRUCache.prototype.get = function (key) {
let index = this.cache.findIndex((item) => item.key === key);
if (index === -1) {
return -1;
}
// 删除此元素后插入到数组第一项
let value = this.cache[index].value;
this.cache.splice(index, 1);
this.cache.unshift({
key,
value,
});
return value;
};
// 实现 put 方法
LRUCache.prototype.put = function (key, value) {
let index = this.cache.findIndex((item) => item.key === key);
// 想要插入的数据已经存在了,那么直接提升它就可以
if (index > -1) {
this.cache.splice(index, 1);
} else if (this.cache.length >= this.capacity) {
// 若已经到达最大限制,先淘汰一个最久没有使用的
this.cache.pop();
}
this.cache.unshift({ key, value });
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
实现2:Map实现,时间复杂度 O(1)
DETAILS
// 上述代码来自 LRU 缓存机制-官方
// 时间复杂度 O(1),因为 Map 既能保持键值对,还能记住插入顺序。
var LRUCache = function (capacity) {
this.cache = new Map();
this.capacity = capacity;
};
LRUCache.prototype.get = function (key) {
if (this.cache.has(key)) {
// 存在即更新
let temp = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, temp);
return temp;
}
return -1;
};
LRUCache.prototype.put = function (key, value) {
if (this.cache.has(key)) {
// 存在即更新(删除后加入)
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// 不存在即加入
// 缓存超过最大值,则移除最近没有使用的
// new Map().keys() 返回一个新的 Iterator 对象
this.cache.delete(this.cache.keys().next().value);
}
this.cache.set(key, value);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
实现3:localStorage
DETAILS
let LRUStorageCache = function (storageKey, capacity) {
this.getStorageData = key => {
let value = localStorage.getItem(key) || "[]";
let valueJson = JSON.parse(value);
return valueJson;
}
this.setStorageData = (key, value = []) => {
let valueStr = JSON.stringify(value);
localStorage.setItem(key, valueStr);
}
this.storageKey = storageKey;
this.cache = () => {
return this.getStorageData(this.storageKey);
}
this.capacity = capacity;
};
LRUStorageCache.prototype.get = function (key) {
let cache = this.cache();
let index = cache.findIndex((item) => item.key === key);
if (index === -1) {
return -1;
}
// 删除此元素后插入到数组第一项
let value = cache[index].value;
cache.splice(index, 1);
cache.unshift({
key,
value,
});
this.setStorageData(this.storageKey, cache);
return value;
};
LRUStorageCache.prototype.put = function (key, value) {
let cache = this.cache();
let index = cache.findIndex((item) => item.key === key);
// 想要插入的数据已经存在了,那么直接提升它就可以
if (index > -1) {
cache.splice(index, 1);
} else if (cache.length >= this.capacity) {
// 若已经到达最大限制,先淘汰一个最久没有使用的
cache.pop();
}
cache.unshift({ key, value });
this.setStorageData(this.storageKey, cache);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
← 05-提高可扩展性 01-HelloVue →