如果笔记

如果笔记

做有价值的技术笔记

性能优化系列3:Vue应用中使用数据缓存

Vue应用中如果没有数据缓存,那么每次打开页面都要请求后端接口获取数据,比如从列表页打开某一个详情页,再后退回列表页时,又要请求一次接口获取列表数据,这显然是不科学的

Vue应用中如果没有数据缓存,那么每次打开页面都要请求后端接口获取数据,比如从列表页打开某一个详情页,再后退回列表页时,又要请求一次接口获取列表数据,这显然是不科学的。 Vue自带一个`keep-alive`的组件,但该组件用起来并不是很方便,尤其是对路由里包含动态参数的,一是不能对该动态路由进行keep-alive,也就是说进入动态路由的页面每次都要请求后端接口,二是控制哪些路由keep-alive哪些不keep-alive,控制起来不够简便。 本文将介绍一个全局缓存插件,以帮助Vue更简单地做数据缓存。该插件支持指定缓存有效时间,并且由于JS对象是引用类型,所以天然保持了Vue数据的响应式。 先看看如何使用,缓存页面级组件的数据: ```javascript import Cache from '@/lib/cache'; export default { components: { ... }, data() { // `return data` 改成 `return Cache(data, expires)` // expires 为缓存有效时间,单位分钟,本例为10分钟 return Cache({ list: [], pageCount: 1, activePage: 1, }, 10); }, created() { // 如果命中缓存,$data将有一个CACHE属性 if (this.$data.CACHE) { return; } // 没命中缓存,请求后端接口 Http.get('/list', (res) => { if (res.code==200) { this.list = res.list; // 我们已经把整个this.$data放入缓存,所以这里无需再手动存储缓存 } }); }, ``` 要缓存页面级组件的数据,你要做的只是把`return data`改成`return Cache(data, expires)`,同时在请求数据之前判断下是不是命中缓存,这样就已经给你的页面级组件加上缓存了!当进入该页面时,Cache会自动判断是否有缓存以及缓存是否有效,有的话取出数据,整个组件的数据全都保留了下来!这些都无需你手动干预。 如果只想缓存某个接口的数据,则使用如下: ```javascript export default { data() { return { list: [], pageCount: 1, activePage: 1, }; }, created() { // 'list@/home' 为缓存key,格式建议为 '组件名或接口名@/所在页面path' let list = Cache.get('list@/home'); if (list) { // 命中缓存 this.list = list; return; } // 没命中缓存,请求后端接口 Http.get('/list', (res) => { if (res.code==200) { this.list = res.list; // 需手动存储缓存,有效时间15分钟 Cache.set('list@/home', res.list, 15); } }); }, ``` 由于缓存key是全局的,所以建议格式如`组件名或接口名@/所在页面path`。 手动清除缓存:`Cache.remove(key)`。 贴上lib/cache.js的代码: ```javascript // 缓存 var _cache = {}; // window.CACHE = _cache; // 开发调试时可打开注释看缓存数据 /*-- 存取整个页面的数据,Cache函数只能存取页面级数据,在data函数里使用 -p obj data 数据 -p num exp 缓存有效时长,单位分钟 -p boolean querySensitive 是否query参数敏感,可选,默认不敏感 -note 删除缓存`Cache.remove(location.pathname)` -note 命中缓存时`this.$data.CACHE`为true */ function Cache(data, exp, querySensitive) { var key = location.pathname; querySensitive && (key += location.search); var val = _cache[key]; if (val && Date.now()<val.t) { val.data.CACHE = true; return val.data; } _cache[key] = { t: Date.now() + exp * 60000, data: data }; return data; } // 存缓存 // key 缓存名称,别以`/`开头,除非你在故意存取整个页面的数据;data 数据;exp 缓存有效时长,单位分钟 Cache.set = function (key, data, exp) { _cache[key] = { t: Date.now() + exp * 60000, data: data }; }; // 取缓存 // key 缓存名称 Cache.get = function (key) { var val = _cache[key]; if (val) { if (Date.now()<val.t) { return val.data; } else { delete _cache[key]; } } return false; }; // 清除缓存 // key 缓存名称 Cache.remove = function (key) { delete _cache[key]; }; export default Cache; ``` 对于页面级组件的缓存,如果对GET参数敏感,即GET参数不同,页面数据也不同,则调用Cache时需要传第三个参数`return Cache(data, expires, true)`。 **特别说明**:本插件是根据`location.pathname`存储页面级组件的数据,所以路由模式只能是history。如果是hash模式,可在data里加上path属性,值为`this.$route.path`,并修改cache.js的代码:`var key = location.pathname`改为`var key = data.path`。 用了数据缓存,再配合上 [滚动条位置管理](https://ifnote.cn/note/134),则体验就更好了。

前端

hahaboy