初试WebStorage之localstorage
今天小试一下html5中引入的localStorage特性(后来查了下localStorage应该是W3C中Web Storage的一部分,而不是Html5), 这个特性在IE8+中也已支持,其他的浏览器应该都已支持(像chrome, firefox一般都会自动升级到最新). 在学习的过程中也参考了一些文章,比如Diveintohtml5系列和 html5demos系列.总之网上的资源还是很多的.下面就拿出我比较简单的测试代码来 说明一下.
首先来段工具代码, 这段放在外部js中在中引入
// 探测浏览器是否支持localStorage
var isSupportLocalStorage = function() {
try {
return 'localStorage' in window && window['localStorage'] != null;
} catch (e) {
return false;
}
};
// 一段老生常谈的添加事件通用方法, 不过这样写更巧妙些
// addEvent会初始化为适合当前浏览器的方法
// 不用每次都判断, 而且对IE中eventHandler的调用做了小小的改进
// 让eventHandler的执行context为触发事件的元素
var addEvent = (function() {
if(document.addEventListener) {
return function(el, type, fn) {
if(el && el.nodeName || el === window) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
for(var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
} else {
return function(el, type, fn) {
if(el && el.nodeName || el === window) {
el.attachEvent('on' + type, function() {
return fn.call(el, window.event);
});
} else if (el && el.length) {
for(var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
}
})();
下面是配合测试的html代码, 测试一共两个页面A和B,访问方式是http://localhost:8080/FrontEnd/A.html(B.html), html部分都是相同的. 一个输入框,一个按钮
下面来看页面A.html中的js代码
if(isSupportLocalStorage()) {
// 清除所有存储的key,value值
// localStorage.clear();
var dataInput = document.getElementById('data'),
saveBtn = document.getElementById('saveBtn');
addEvent(saveBtn, 'click', function () {
// 按下按钮存下当前输入框中的值
localStorage.setItem('storage-event-test', dataInput.value);
});
// 给window监听storage事件
addEvent(window, 'storage', function (event) {
// 查看event对象内容
// console.dir(event);
// 输出oldValue和newValue 以作观察
console.log('key: %s, old value: %s, new value: %s', event.key, event.oldValue, event.newValue);
});
// 存储数字
localStorage.setItem('number', 1);
// 存储对象 因为localStorage最终都是以String来存储的 所以如果要存储对象 可以覆写它的toString方法
// 按照你想要的字符串格式来存储, 然后取出后再做相应的处理, 这里就拿json格式做个例子
localStorage.setItem('obj', "{'name':'Andrew', 'job': 'Developer'}");
// 常规的存储
localStorage.setItem('string', 'hello world');
} else {
// 这里可以做些降级的方案, 当然也可以给出一个不支持的提示
var span = document.createElement("span");
span.style.color = 'red';
span.innerHTML = 'oops, your browser dones\'t support localStorage yet, :(';
document.getElementsByTagName('body')[0].appendChild(span);
}
再来看一下B.html中的js代码, 基本和A.html中的相同, 只是中间一段存储代码改成读取而已, 比较简单
if(isSupportLocalStorage()) {
//localStorage.clear();
var dataInput = document.getElementById('data'),
saveBtn = document.getElementById('saveBtn');
addEvent(saveBtn, 'click', function () {
localStorage.setItem('storage-event-test', dataInput.value);
});
// 给window监听storage事件
addEvent(window, 'storage', function (event) {
// 查看event对象内容
// console.dir(event);
// 输出oldValue和newValue 以作观察
console.log('key: %s, old value: %s, new value: %s', event.key, event.oldValue, event.newValue);
});
// 取出来也是String类型的, 要用parseInt转换下
console.log(parseInt(localStorage.getItem('number')));
// 取出来的json格式字符串要用eval解析一下 转换成对象
console.dir(eval('(' + localStorage.getItem('obj') + ")"));
// 普通的读取
console.log(localStorage.getItem('string'));
} else {
var span = document.createElement("span");
span.style.color = 'red';
span.innerHTML = 'oops, your browser dones\'t support localStorage yet, :(';
document.getElementsByTagName('body')[0].appendChild(span);
}
我先在firefox5中进行测试,一开始还遇到了一个可笑的问题, 没有通过启动本地的运用服务器来访问(以http://localhost:8080/...),直接是个静态页面(以file:///"形式), 在firebug下搞了半天也没看到window下的localStorage属性,而且storage事件也根本不触发.放到IE9中,F12开发者工具的调试输出面板中直接报个错, localStorage为null或未定义. 后来google了一下,在stackoverflow中找到了答案, localStorage要通过域名访问的方式才能起作用.总算能继续进行下去了: )
在firefox5中存储和读取都是正常的, 但是对storage事件的触发似乎有点问题, 自身页面进行setItem后没有触发window的storage事件, 但是同时访问A.html和B.html, 在A页面中进行 setItem能触发B页面中window的storage事件, 同样的在B页面中进行setItem能触发A页面中window的storage事件. 在IE9中, 页面自身的设值能触发当前页面的storage事件,同样当前页面的设值能触发同一"起源"下其他页面window的storage事件,这看起来似乎更让人想的通些.
关于"起源"这个词Dev.Opera-WebStorage中用的是origin. 我就姑且把origin翻译成蹩脚的"起源"吧, 文章最后关于web storage的注意点里有这么一句: Storage per origin:All storage from the same origin will share the same storage space 并且要协议 + 域名 + 端口一样才能算同一origin, 这个origin下的页面才能共享一个storage space. 有兴趣的可以去读下此文章.
还有firefox中跨页面触发,好像也有些让人不解. 我的测试结果是这样的(dataInput.value直接用字符串进行代替):
-
A中 setItem('storage-event-test', 'aaaa') -> B的console输出oldValue: , newValue: aaaa -
B中 setItem('storage-event-test', 'bbbb') -> A的console输出oldValue: , newValue: bbbb -
A中 setItem('storage-event-test', 'cccc') -> B的console输出oldValue: aaaa, newValue: cccc -
B中 setItem('storage-event-test', 'dddd') -> A的console输出oldValue: bbbb, newValue: dddd
我所预期的结果是,两个页面应该共享同一个storageArea
-
A中 setItem('storage-event-test', 'aaaa') -> B的console输出oldValue: , newValue: aaaa -
B中 setItem('storage-event-test', 'bbbb') -> A的console输出oldValue: aaaa, newValue: bbbb -
A中 setItem('storage-event-test', 'cccc') -> B的console输出oldValue: bbbb, newValue: cccc -
B中 setItem('storage-event-test', 'dddd') -> A的console输出oldValue: cccc, newValue: dddd
这个结果一看就是不怎么对劲, 好像localStorage中的storageArea是各自独立的,而非对于同一个"起源"共享的.但是A页面中的那段存储在B页面中却能正常读取. 在IE9下结果是我所预期的那种. 所以搞到最后我就纳闷了难道是firefox的bug还是我对localStorage的理解还有出入, 如果有园友知道其中的缘由, 希望能留言指导一下, 先谢谢了.
在IE9里发现一个问题,相同的key,不管你value是否与之前一样,都会触发storage事件,而firefox中不会,只有当value与之前不同时,才会触发.