- web前端
- javascript
- FeHelper
- css
- PHP
- browser extension
- chrome
- 技术随笔
- bluehost
- 微信
- PSpriter
- 浏览器扩展
- html5
- webapp
- 二维码
- FE
- es5
- 效率
- 矩形布局
- node-webkit
- canvas
- bae
- localstorage
- Css Sprites
- notification
- baidufe
- shell
- mac
- 桌面客户端
- 图片合并
- 跨域
- apt-cyg
- 用户反馈
- zoom-detect
- IE6
- button巧用
- Firefox
- 精美效果
- plist
- 网页变灰
- Google收录
- emmet
- beautify
- logo
- 编程语言趋势
- 域名绑定
- 字体检测
- 遮罩
- manifest.json
- global vars
文章写了都一年多了,一直没个合适的地方放,现在终于可以搬上来了。
背景
先看看各种本地存储的变革:
-
Cookies:浏览器均支持,容量为4KB
-
UserData:仅IE支持,容量为64KB
-
Flash:100KB
-
Google Gears SQLite :需要插件支持,容量无限制
-
LocalStorage:HTML5,容量为5M
现准备在项目中试图取代cookie的实现,基本分析如下:
-
每次和服务器端进行交互,cookie都会在请求中被携带,cookie过多,也造成带宽的浪费
-
cookie的容量很小,或许无法满足当今互联网的本地存储需求
-
在IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+等平台下,已经完全支持HTML5的LocalStorage
-
在IE7即以下版本中,可以使用UserData来代替cookie,而且同样比cookie保险
-
用户可能清cookie,但不见得知道去清UserData或者LocalStorage,这也增强了一道代码保险
到底用啥来取代?
-
UserData:仅IE可用
-
Flash:存储空间够了,也还挺好,可这玩意儿不是HTML原生的
-
Google Gears:存储空间没啥限制,就是得装额外的插件
-
HTML5-LocalStorage:官方建议每个站点可以本地存储5M的内容,非常大了
最后再分析一下现在咱们针对的浏览器:IE系列、FF、Chrome、Safari、Opera,外加双核的遨游、QQ浏览器、搜狗浏览器
其中,现在的FF、Chrome、Safari、Opera已经完全支持HTML5-LocalStorage
双核的那些个浏览器,要么Webkit内核,要么IE内核(大多都是IE8的内核了),所以这些也是支持HTML5-LocalStorage的
最后就剩IE7及其以下版本,对于专门的IE,就用它们自家提供的UserData了,处理很方便
总结:用UserData和HTML5-LocalStorage结合的方式,来取代cookie!
UserData的存储情况:
UserData行为通过将数据写入一个UserData存储区(UserData store)来保存数据,userData可以将数据以XML格式保存在客户端计算机上。
该数据将一直存在,除非你人为删除或者用脚本设置了该数据的失效期。
从上面的表格可以看出,就算是一个受限(Restricted)的站点,单个文档也能存64KB的数据,整个Domain也能装得下640KB的东西。
要了解更多UserData的东西,可以点击这里
关于Expires
我们都知道,采用cookie来进行本地数据缓存,可以设定一个生命周期,在IE中采用UserData进行替代,能完美的实现。
但是对于HTML5提供的LocalStorage则没有提供现成的API,来设置某本地存储的生命周期,只能采取一些极端的手段进行模拟实现。
关于数据的批量存储、提取、删除
一个好用的组件库,应该提供更加便捷的API,原生的cookie、UserData、LocalStorage都没有提供现成的接口可调用,所以,在这里,我们来包装一个,使其拥有这样的批量接口。
代码实现
1、IE中的UserData实现
原理很简单,就是创建一个HTML节点,为其增加一个行为(behavior):#default#userData,把待存储的数据放到该节点的属性上(setAttribute),再保存到本地即可(save)。
创建html实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* 创建并获取这个input:hidden实例
* @return {HTMLInputElement} input:hidden实例
* @private
*/
function
_getInstance(){
//把UserData绑定到input:hidden上
var
_input =
null
;
//是的,不要惊讶,这里每次都会创建一个input:hidden并增加到DOM树种
//目的是避免数据被重复写入,提早造成“磁盘空间写满”的Exception
_input = document.createElement(
"input"
);
_input.type =
"hidden"
;
_input.addBehavior(
"#default#userData"
);
document.body.appendChild(_input);
return
_input;
}
|
本地数据存储:
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
|
/**
* 将数据通过UserData的方式保存到本地,文件名为:文件名为:config.key[1].xml
* @param {String} key 待存储数据的key,和config参数中的key是一样的
* @param {Object} config 待存储数据相关配置
* @cofnig {String} key 待存储数据的key
* @config {String} value 待存储数据的内容
* @config {String|Object} [expires] 数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间
* @private
*/
function
__setItem(key,config){
try
{
var
input = _getInstance();
//创建一个Storage对象
var
storageInfo = config || {};
//设置过期时间
if
(storageInfo.expires) {
var
expires;
//如果设置项里的expires为数字,则表示数据的能存活的毫秒数
if
(
'number'
==
typeof
storageInfo.expires) {
expires =
new
Date();
expires.setTime(expires.getTime() + storageInfo.expires);
}
input.expires = expires.toUTCString();
}
//存储数据
input.setAttribute(storageInfo.key,storageInfo.value);
//存储到本地文件,文件名为:storageInfo.key[1].xml
input.save(storageInfo.key);
}
catch
(e) {
}
}
|
再看userData本地数据的读取:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/**
* 提取本地存储的数据
* @param {String} config 待获取的存储数据相关配置
* @cofnig {String} key 待获取的数据的key
* @return {String} 本地存储的数据,获取不到时返回null
* @example
* qext.LocalStorage.get({
* key : "username"
* });
* @private
*/
function
_getItem(config){
try
{
var
input = _getInstance();
//载入本地文件,文件名为:config.key[1].xml
input.load(config.key);
//取得数据
return
input.getAttribute(config.key) ||
null
;
}
catch
(e) {
return
null
;
}
}
|
模拟remove操作:
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
|
/**
* 移除某项存储数据
* @param {Object} config 配置参数
* @cofnig {String} key 待存储数据的key
* @private
*/
function
_removeItem(config){
try
{
var
input = _getInstance();
//载入存储区块
input.load(config.key);
//移除配置项
input.removeAttribute(config.key);
//强制使其过期
var
expires =
new
Date();
expires.setTime(expires.getTime() - 1);
input.expires = expires.toUTCString();
input.save(config.key);
//从allkey中删除当前key
//下面的代码用来记录当前保存的key,便于以后clearAll
var
result = _getItem({key : _clearAllKey});
if
(result) {
result = result.replace(
new
RegExp(
"(^|\\|)"
+ config.key +
"(\\||$)"
,
'g'
),
''
);
result = {
key : _clearAllKey,
value : result
};
//保存键
__setItem(_clearAllKey,result);
}
}
catch
(e) {
}
}
|
2、再看HTML5-LocalStorage中expires的模拟:
在进行数据存储的时候,单独多存一个字段:key + ".expires",如果传入的expires为数字类型,单位则是毫秒(ms)
1
2
3
4
5
6
7
8
9
10
11
12
|
window.localStorage.setItem(storageInfo.key,storageInfo.value);
// 如果需要指定生命周期
if
(config.expires) {
var
expires;
//如果设置项里的expires为数字,则表示数据的能存活的毫秒数
if
(
'number'
==
typeof
storageInfo.expires) {
expires =
new
Date();
expires.setTime(expires.getTime() + storageInfo.expires);
}
window.localStorage.setItem(storageInfo.key +
".expires"
,expires);
}
|
在数据读取的时候,通用读取这个字段,判断时间是否超出了生命周期
1
2
3
4
5
6
7
8
9
10
11
12
13
|
result = window.localStorage.getItem(config.key);
//过期时间判断,如果过期了,则移除该项
if
(result) {
var
expires = window.localStorage.getItem(config.key +
".expires"
);
result = {
value : result,
expires : expires ?
new
Date(expires) :
null
};
if
(result && result.expires && result.expires <
new
Date()) {
result =
null
;
window.localStorage.removeItem(config.key);
}
}
|
3、提取所有key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* 获取所有的本地存储数据对应的key
* <pre><code>
* var keys = qext.LocalStorage.getAllKeys();
* </code></pre>
* @return {Array} 所有的key
*/
getAllKeys :
function
(){
var
result = [];
//支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
if
(_isSupportLocalStorage) {
var
key;
for
(
var
i = 0,len = window.localStorage.length;i < len;i++){
key = window.localStorage.key(i);
if
(!/.+\.expires$/.test(key)) {
result.push(key);
}
}
}
else
if
(_isSupportUserData) {
//IE7及以下版本,采用UserData方式
result = _getAllKeys();
}
return
result;
}
|
4、清除所有本地存储的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* 清除所有本地存储的数据
* <pre><code>
* qext.LocalStorage.clearAll();
* </code></pre>
*/
clearAll :
function
(){
//支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
if
(_isSupportLocalStorage) {
window.localStorage.clear();
}
else
if
(_isSupportUserData) {
//IE7及以下版本,采用UserData方式
_clearAll();
}
}
|
关于使用方法
1、数据存储:qext.LocalStorage.set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 保存单个对象到本地
qext.LocalStorage.set({
key :
"username"
,
value :
"baiduie"
,
expires : 3600 * 1000
/*单位:ms*/
});
// 保存多个对象
qext.LocalStorage.set([{
key :
"username"
,
value :
"baiduie"
,
expires : 3600 * 1000
/*单位:ms*/
},{
key :
"password"
,
value :
"zxlie"
,
expires : 3600 * 1000
/*单位:ms*/
}]);
|
2、数据提取:qext.LocalStorage.get
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//获取某一个本地存储,返回值为:{key:"",value:"",expires:""},未取到值时返回值为:null
var
rst = qext.LocalStorage.get({
key :
"username"
});
//获取多个本地存储,返回值为:["","",""],未取到值时返回值为:[null,null,null]
qext.LocalStorage.get([{
key :
"username"
},{
key :
"password"
},{
key :
"sex"
}]);
|
3、数据删除:qext.LocalStorage.remove
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//删除一个本地存储项
qext.LocalStorage.remove({
key :
"username"
});
//删除多个本地存储项目
qext.LocalStorage.remove([{
key :
"username"
},{
key :
"password"
},{
key :
"sex"
}]);
|
4、清空所有数据:qext.LocalStorage.clearAll
1
2
|
// 清空所有本地存储的数据
qext.LocalStorage.clearAll();
|
5、获取所有本地存储的key:qext.LocalStorage.getAllKes
1
2
|
// 获取所有本地存储的key
var
keys = qext.LocalStorage.getAllKeys();
|
源码Share
可以点击这里下载:http://www.baidufe.com/upload/67901343628004.rar
ChangeLog:
2010-4:
1、初版
2012-07-30:
1、修复qext.LocalStorage.set方法对expires的支持