在写基于express、vuejs博客的小项目过程中,折腾了下在vuejs中怎么使用浏览器缓存请求。

原理是利用vue-resource拦截器interceptor,判断当前请求是否存在localStorage里,有则返回缓存的内容;没有则请求服务器,并在localStorage写入缓存。

用到的依赖包:

详细代码在https://github.com/liukaijv/lnode-blog/tree/master/frontend

相关代码

vue入口文件main.js:

1
2
3
4
5
6
7
8
9
10
import Vue from 'vue';
import VueResource from 'vue-resource';
import Cache from 'lscache';

Vue.prototype.$cache = Cache;
Vue.cache = Cache;

import httpCache from './lib/cache';
httpCache(Vue);

缓存拦截器cache.js:

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
import _ from 'lodash';

export default function (Vue){
Vue.http.interceptors.push((request, next) => {

// lifetime为缓存时间
let cached, key, lifetime;

if(request.cache !== undefined && /^(GET|JSONP)$/i.test(request.method)) {

if (_.isObject(request.cache)) {
lifetime = request.cache.lifetime;
key = '_resource.' + request.cache.key;
} else {
lifetime = request.cache;
key = request.url;
}

// 不需要缓存的请求,添加参数no_cache=true
let no_cache = request.params.no_cache;

cached = Vue.cache.get(key);

if (cached && !no_cache) {
// 重写返回数据
request.client = function (request) {
return request.respondWith(cached.body, {ok: true, status:200});
};
}
}

next((response) => {
if (!cached && response.ok) {
Vue.cache.set(key, response, lifetime);
}

});
});
}

说明

关键点请求的client,返回数据{ok: true}必须有,这样才能正确返回数据。

1
2
3
request.client = function (request) {                    
return request.respondWith(cached.body, {ok: true, status:200});
};

具体请查看源码https://github.com/pagekit/vue-resource/blob/master/src/http/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
return client(new Request(options)).then((response) => {

// 原因在这里
return response.ok ? response : Promise.reject(response);

}, (response) => {

if (response instanceof Error) {
error(response);
}

return Promise.reject(response);
});