JavaScript本地存储(3) : DOM Storage

上回我们在《JavaScript本地存储(2) : IE Only的userData》中提到了userData,当然这个存储方式只能支持IE系列的浏览器,从长远来看这种方法应该是被抛弃的,目前新技术发展很快,比如最新的HTML5技术,随之而来的是更为标准的JavaScript本地存储模式,那就是DOM Storage。更多的可以参考W3C的标准化文档《Web Storage》,其为我们提供了两种模式的本地存储,一个是sessionStorage,另一个是localStorage,今天我们先重点介绍localStorage。
同样的这两种存储模式都是基于标准的Storage接口的,其接口规范如下:

1
2
3
4
5
6
7
8
interface Storage {
  readonly attribute unsigned long length;
  DOMString key(in unsigned long index);
  getter any getItem(in DOMString key);
  setter creator void setItem(in DOMString key, in any value);
  deleter void removeItem(in DOMString key);
  void clear();
};

大家应该对这个非常熟悉,因为有些地方类似于我们在第一篇介绍的IStorage的接口方法,同样的基于这样的标准我们就可以很轻松的实现我们的IStorage接口了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var DOMStorage = function() {
  this.domStorage = null;
  this.domain = location.hostname;
  if (!this.domStorage) {
    this.domStorage = window.localStorage ||
            window.globalStorage &&
            window.globalStorage[this.domain];
  }
 
  this.setItem = function(key, value) {
    this.domStorage.setItem(key, value);
  }
 
  this.getItem = function(key) {
    return this.domStorage.getItem(key);
  }
 
  this.remove = function(key) {
    this.domStorage.removeItem(key);
  }
}

大家可能奇怪,为什么会出现window.globalStorage这样的东东,原来localStorage只是FireFox 3.5及以上版本支持,对于低于这个版本的FireFox浏览器,我们可以用globalStorage变通一下,当然更详细的信息我们可以参考Mozilla的官方文档《DOM Storage》。下面只列出globalStorage的域功能,globalStorage有个域标识,相当于访问权限控制,具体如下。

  • globalStorage[‘developer.mozilla.org’] 在developer.mozilla.org下面所有的子域都可以通过这个存储对象来进行读和写。
  • globalStorage[‘mozilla.org’] 在mozilla.org域名下面的所有网页都可以通过这个存储对象来进行读和写。
  • globalStorage[‘org’] 在.org域名下面的所有网页都可以通过这个存储对象来进行读和写。
  • globalStorage[”] 在任何域名下的任何网页都可以通过这个存储对象来进行读和写。

肯定会有朋友问,IE支持localStorage么,据我所知,目前也只是IE8及以上版本支持localStorage,那么低于IE8版本的可以用globalStorage?答案是否定的,globalStorage貌似只有火狐支持,那么低于IE8版本的IE浏览器就没有办法了吗?哈,你忘记了我先前介绍的userData的IE专用办法了,关键时刻还是可以请它来帮忙的。

下一篇我将重点介绍如何整合这些存储方式。哦,对了,差点忘了sessionStorage,这个好理解,存储操作方式和localStorage一样,只不过sessionStorage是浏览器对话模式的,也就是说你关了浏览器就什么都没有了。

最后给出篇参考文章:《跨浏览器的本地存储(二):DOM:Storage》

使用DOMContentLoaded取代部分window.onload

使用DOMContentLoaded的好处是不言而喻的,其可以在DOM加载解析完毕后立即执行,而不是像window.onload那样还要继续等待所有外部图片什么的都加载完成才执行,所以在这点上DOMContentLoaded的效率功能要大于window.onload,一般适合于绑定事件到指定元素上时使用。

1
2
3
4
5
6
if(document.addEventListener){
  document.addEventListener("DOMContentLoaded",
    function() {
        alert('DOMContentLoaded is execute')
    }, false);
}

大家看到这段代码肯定非常熟悉,是的,想必大家都用过下面这段辅助函数,主要用于给元素绑定事件的,注意是绑定事件,多个绑定事件将依次触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function addListener(element, e, fn) {
    if (element.addEventListener) {
        element.addEventListener(e, fn, false);
    } else {
        element.attachEvent("on" + e, fn);
    }
}
 
// 比如绑定window.onload事件
addListener(window, "load", 
    function() {
        alert('window.onload is execute');
    }
);

说到这里大家就有疑问了,IE系列的浏览器不支持.addEventListener方法,这也就是在addListener函数里面要做个判断的原因,如果不支持就使用.attachEvent方法,那回到一开始的DOMContentLoaded的代码,那么这段代码很明显就不能支持IE系列浏览器了,我们能不能使用addListener函数呢?很遗憾,问题不在于这儿,而是IE系列浏览器不能很好的支持DOMContentLoaded,所以即使使用了addListener这样的辅助函数依然无济于事。

注意 : 微软最新发布的Internet Explorer 9(IE9)已经能够支持.addEventListener和DOMContentLoaded。

真的没有办法了吗?其实办法也不是没有,网上就有人总结出了两种方法:

  1. 一种是创建空script标签,属性拥有defer,然后待onreadystatechange为complete时激发DOMContentLoaded。
  2. 一种是通过调用doScroll(‘left’)的原理去判断DOMContentLoaded。

如果大家对代码实现比较感兴趣的话可以参考《IE里模拟DOMContentLoaded事件》这篇文章。

说到这里,大家也许在想有没有更好的封装函数供我们使用呢?幸运的是Jesse Skinner已经在文章《addDOMLoadEvent》给出了其设计的函数脚本adddomloadevent.js,大家可以参考下。