sessionStorage,UserDataStorage,cookie全兼容写法存在的问题

最近央视播出了中国诗词大赛,看到了一首诗,送给大家大笑


《春宵·春宵一刻值千金》

作者:苏轼 【宋代】 

春宵一刻值千金,花有清香月有阴

歌管楼台声细细,秋千院落夜沉沉。



好了,言归正传,今天在项目中为了性能问题,打算用本地存储来保存网页的状态,h5中推出两个非常强大的API---sessionStorage和localStorage,经实际检测发现可以兼容到IE8,但是IE还有自己的本地存储方案--UserDataStorage,可以兼容到IE5。可能有人会问,为什么不用cookie,前面说到了性能的问题,cookie的作用域在指定的路径以及它的子路径都有效,并且会附加到请求中,这会发送很多不必要的数据。


于是写了以下兼容所有浏览器的代码,那么问题来了,先遇到了IE不能识别自己的load()方法,然后又遇到了手机浏览器的问题,下面将会细说。


var storageObj = window.sessionStorage || ( window.UserDataStorage && new UserDataStorage() )|| new cookieStorage();



其中cookieStorage.js文件如下,cookie没有对应的API,为了和sessionStorage对象使用相同的方法,需要进行封装。

function cookieStorage( path, maxage ){

	var cookie = ( function(){

		var cookie =  {};
		var all = document.cookie;

		if ( all === '' ) {

			return cookie;

		}

		var list  = all.split( '; ' );
		for( var i = 0; i < list.length; i++ ){

			var tmp = list[i];
			var p = tmp.indexOf( '=' );
			var name = tmp.substring( 0, p );
			var value = tmp.substring( p + 1 );
			value = decodeURIComponent( value );
			cookie[name] = value;

		}

		return cookie;

	}() );

	var keys = [];
	for( var key in cookie ){

		keys.push( key );

	}

	this.length = keys.length;

	this.key = function( n ){

		if( n < 0 || n >= keys.length ){

			return null;

		}

		return keys[n];

	};

	this.getItem = function( name ){

		return cookie[name] || null;

	};

	this.setItem = function( key, value ){

		if ( !( key in cookie ) ) {

			keys.push( key );
			this.length++;
		}

		cookie[key] = value;

		var tmp = key + '=' + encodeURIComponent( value );
		if ( maxage ) {

			tmp += '; max-age=' + maxage;

		}
		if ( path ) {

			tmp += ';  path=' + path;

		}

		document.cookie = tmp;

	};

	this.removeItem = function( key ){

		if ( !( key in cookie ) ) {

			return ;

		}

		delete cookie[key];

		for( var i = 0; i < keys.length; i++ ){

			if ( keys[i] === key ) {

				keys.splice( i, 1 );
				break;

			}
		}

		this.length--;
		document.cookie = key + '=; max-age=0';

	};

	this.clear = function(){

		for( var i = 0; i < keys.length; i++ ){

			document.cookie = keys[i] + '=; max-age=0';

		}

		cookie = {};
		keys = [];
		this.length = 0;

	};

}



注意:document.cookie = tmp相当于add函数,并不是重置cookie


其中userDataStorage.js,同cookie一样也需要封装,具体的使用方法请查看IE文档,先贴代码如下:

function UserDataStorage( maxage ){

	var memory = document.createElement( 'div' );
	memory.style.display = 'none';
	memory.style.behavior = 'url("#default#userData")';
	document.body.appendChild( memory );

	if ( maxage ) {

		var now = new Date().getTime();
		var expires = now + maxage * 1000 ;
		memory.expires = new Date( expires ).toUTCString();

	}

	memory.load( 'MyDataStorage' );

	this.getItem = function( key ){

		return memory.getAttribute( key ) || null;
	};

	this.setItem = function( key, value ){

		memory.setAttribute( key, value );
		memory.save( 'MyDataStorage' );

	};

	this.removeItem = function( key ){

		memory.removeAttribute( key );
		memory.save( 'MyDataStorage' );
	};

}


问题来了


第一,userDataStroage仅适用于IE,所以为了性能加入以下代码


<!--[if IE]>
      <script src="/userDataStorage.js"></script>
<![endif]-->

经浏览器查看,这句代码在IE10和IE11中起到了反作用,就像其他浏览器一样,userDataStorage.js被过滤了惊讶,晕,这不是IE才执行的代码? IE10和IE11不是IE?????



但是IE9及以下能够加载,在网上查了一下可以添加<meta http-equiv="X-UA-Compatible" content="IE=9">指定IE9模式来解析。但是这样就不能用IE10的新特性了。


其次,IE的UserDataStorage需要用到.load()来加载数据,但是亲测在IE8和IE9中不能识别这个函数,打断点发现新建的标签根本没有这个方法。






我的天啊,这是神马鬼。


然后老老实实的用cookie来做不兼容sessionStorage的备选方案,但在使用的时候发现出现两个同名但不同值的cookie(如下图),我和我的小伙伴都惊呆了惊讶,后来才发现,是没有设置路径,cookie默认是用当前文档的路径来做路径的,默认失效时间是session时间,路径不同则cookie也不同,即使名称一样。在不指定路径的情况下,两个不同路径的文件设同名的cookie就会出现以上情况,具体的路径的设置和时间设置以及作用域就不多说了,可参考其他文档。






顺便说下在google中查看cookie的两种方法



1、在浏览器的地址栏头部点击那个感叹号,可以查看到详细的路径信息





2、在控制台看,路径信息被遮挡了,只能看到部分





于是我设置了统一的路径,这样就不会出现同名的cookie了,新值只会覆盖旧值。


var Storage =  window.sessionStorage || new cookieStorage( '/cgi-bin/luci/' );

你以为这就搞定了吧,问题又出现了哭在手机360浏览器,经检测是支持sessionStorage的,但是发现当设了sessionStorage后,跳转页面,sessionStorage作用域变了,获取不到原来设的那个sessionStorage的值了,值为null,郁闷,但是在其他手机浏览器是好的,还有就是在手机浏览器无痕模式下,也会失效,最后为了兼容只能采用cookie的方案了,如果你的项目要求兼容的浏览器不那么严格的话,可以尝试以上方案。至于无痕模式的解决方案还在探索中,以后会发出来。


总结,做个前端真不容易啊!一堆堆的坑等着你跳。





posted @ 2017-02-25 20:05  zc的救赎  阅读(1101)  评论(0)    收藏  举报