初试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与之前不同时,才会触发.

posted @ 2011-07-04 11:15 Andy Zhang 阅读(723) 评论(0) 编辑 收藏