TA的每日心情 | 衰 2021-2-2 11:21 |
---|
签到天数: 36 天 [LV.5]常住居民I
|
最近在做在线考试系统时遇到这样一个问题,就是当考生考试时可能出出现断网、关闭浏览器,刷新等问题,此时数据又没有实时写入数据库,所以造成数据丢失问题,,所以这里就需要用到本地存储,一开始想到的是用cookie,但是cookie缺失太小了是有4k。
P, O" y: }+ B/ ]/ M: A. u& P 本地持久化存储一直是本地客户端程序优于 web 程序的一个方面。对于本地应用程序,操作系统会一共一个抽象层,用于存储和获取特定于应用程序的数据,例如用户设置或者运行时状态。这些值可以被存储于注册表、INI 文件,或者其他什么地方,这取决于操作系统的实现。如果你的本地应用程序需要不简单是键值对形式的本地存储,你也可以使用嵌入式数据库、发明你自己的文件格式,或者其他很多种解决方案。, q! C& F3 R9 }/ g( e: q
UserData实现方式:5 U7 b# {* i5 S" j$ ?( k# O6 ]6 Y6 ?7 a
userData行为通过将数据写入一个UserData存储区(UserDatastore)来保存数据,userData可以将数据以XML格式保存在客户端计算机上,如果你用的是 Windows 2000 或者 Windows XP,是保存在C:\Documents and Settings\Liming\UserData\文件夹下(如果操作系统不是安装在C盘,那么C就应该是操作系统所在的分区)。
: i2 `6 \9 l. d' u) Y+ T 该数据将一直存在,除非你人为删除或者用脚本设置了该数据的失效期。/ L4 i/ C+ j7 f7 j: `$ ]2 z/ V
userData行为提供了一个比Cookie更具有动态性和更大容量的数据结构。每页的UserData存储区数据大小可以达到64 Kb,每个域名可以达到640 Kb。
9 b3 ^$ l' K5 U- m+ X3 | userData行为通过sessions为每个对象分配UserData存储区。使用save和load方法将UserData存储区数据保存在缓存(cache)中。一旦UserData存储区保存以后,即使IE浏览器关闭或者刷新了,下一次进入该页面,数据也能够重新载入而不会丢失。
6 S' H/ [, \7 e+ J' _0 c 但是,UserData是IE的东西,所以其他浏览器不兼容。% \0 J( I: C* G p4 T
HTML5 storage实现方式:% z3 ?6 j, K0 ?6 {& e/ u
HTML5 storage提供了一种方式让网站能够把信息存储到你本地的计算机上,并再以后需要的时候进行获取。这个概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候cookie都会被发送过去。HTML5的storage是存储在你的计算机上,网站在页面加载完毕后可以通过javascript来获取这些数据。
9 z( b- ]/ O" U' X8 Q3 x, g' U0 f p \% Z' c4 I+ m& f
由于HTML5 storage IE8一下浏览器 所有IE8一下版本要做判断使用UserData的方式实现。具体代码已封装。说明一下 jQuery.browser建议弃用,可以使用jQuery.support来代替。8 G7 K/ h5 V" }, p; v8 O" H* h
页面展示:6 H8 s: h. [3 j/ `$ l
w/ q- s4 D+ N7 E
1 ?1 p2 y( N7 g- <!doctype html>
5 `- ~/ f+ p i1 q: J$ l1 Y$ s5 N - <html>
@2 d6 U+ b# ^( s! g: z - <head>
# ^" W$ h+ U3 a! u2 g7 o3 r8 @ - <title>科帮网在线考试本地存储Powered by 52itstyle</title>
2 s5 H4 P& ]7 K- g - <meta charset="utf-8" />
! o7 _$ l3 \ e - <script src="../js/jquery-1.8.3.js"></script> y; l3 T: X9 L: h6 H4 i. I. |
- <script src="../js/localstorage.js"></script>& C5 f" o2 \0 r& i, K
- <script src="../js/jquery.utils.js"></script>
$ x- s5 G5 I" m! D" M i8 g( _ - <script type="text/javascript">' A" N" p4 P* r7 o. N
- var studentID = "007";1 J M, [& Y4 t% K' K" J3 ~
- var ExamID = "52itstyle";' ~" O8 @3 K' B. G4 O5 P
- var quesNumber = 3;
% y7 E9 S# y5 W - $(function(){
6 p& @& T6 S2 `' q- S$ R - showQuestion();$ m$ }! C. p6 {+ r% x
- $("input").click(function(){8 D% D, h6 U1 J
- var QuestionID = $(this).attr("name");$ r* M& o/ j2 Z) J* \
- var ExamAnswer = $(this).val();) l5 F6 o( M4 M! w4 I& H! z
- qext.LocalStorage.save(studentID,ExamID,QuestionID,ExamAnswer);8 N+ z, Y R u m/ N! T$ P
- });
* }# G4 w7 c' U9 c' P" V2 c - });
6 I/ ~. d$ o2 W+ w: x+ c - /**
5 d6 J" t- K! f( { - * 读取本地存储答案并展示(科帮网http://www.52itstyle.top)
4 z! \5 P1 N, e# U/ m - * java爱好者QQ群:26490602$ ?( B2 q% O" ^. O! Y* I
- */
4 { k! B8 R4 [& b; `+ C# O( s% C7 C - function showQuestion(){
+ Q" h+ b) k& B3 I, Q - for(var i=1;i<=quesNumber;i++){
- i ^: |5 F# T7 X - var rst = getPerQuesInfo(i);
& Z1 _1 @% W* `3 v8 n - if(null!=rst){ z2 n) M* s8 _. _
- var obj = eval("("+rst+")"); + R5 _: o2 U5 r
- var examAnswer = obj.ExamAnswer;
: i( ?/ b* h. X) J7 H5 ^ - $("input[name="+i+"]").val(examAnswer)4 ?: ^3 q% {! l
- } b& D" W' o J2 [- ?& k# s- @7 r+ i
- }
( B0 c# ?6 Z; ~8 ]1 d. G - }+ k: ]6 Y& h# w5 n7 {) o0 l
- /**9 o6 Z9 G! j6 t& o, s1 Y T/ Q
- * 获取单个试题信息(科帮网http://www.52itstyle.top)
8 ^* p$ x9 ^7 p! y( l - * java爱好者QQ群:26490602" b9 C' g# {% I$ G9 P0 M
- */
/ u/ Z$ K1 S7 Y; E" e( F! y1 Z - function getPerQuesInfo(QuestionID){
6 i* r% z, J/ V3 Z - var examKey = studentID+ExamID+QuestionID;( N5 ]( {) x- H; u4 B4 g: Z: T
- var rst = qext.LocalStorage.get({, Y3 C" g2 }& K- ^; h) x q6 E: t
- key : examKey
}/ t/ m& D k: o" c - });3 J$ M0 Q4 H0 Q; o i
- return rst;
# }; s/ W4 h! M! j - }
/ t: y1 {4 ^$ |9 u& d4 z3 O - </script>, H* L3 y3 b/ w5 t
- </head>
* Q' p. a4 o9 S+ }% e5 W' j3 b - <body>! P. [* @% D0 `, d1 J
- <div id="1">成吉思汗有几个老婆?</div>! h, A# P' g8 J
- <div>
3 e; R5 p+ s) O" o4 I - <input type="radio" value="A" name="1" />A 1
& Y k* r& j8 s% C - <input type="radio" value="B" name="1"/>B 2 1 l4 t8 A$ b% A! W; M
- <input type="radio" value="C" name="1"/>C 3
' h# ?/ ~8 e5 e4 t/ | - <input type="radio" value="D" name="1"/>D 4# H3 f" c( p; {# N
- </div>7 B* T3 B% P: m
- <div>成吉思汗有几个老婆?</div>
8 }: X3 j" Z' u3 d* ?0 h - <div>
$ g& L! u8 g/ ~' D7 F- V/ R - <input type="radio" value="A" name="2" />A 1
) x/ ^+ X" m$ x. }/ ] - <input type="radio" value="B" name="2"/>B 2
. H$ F3 Y$ P! c7 Q% V5 e - <input type="radio" value="C" name="2"/>C 31 H6 Z2 R% l/ h7 `# A. H5 D. b
- <input type="radio" value="D" name="2"/>D 4
! f6 A4 X1 X5 c1 o9 M4 s5 x - </div>4 } e% J# X; n- x8 K
- <div>小伟有几个老婆?</div>3 l# d) ^; K7 C$ Q9 J
- <div>% R* V1 ^+ s5 m5 ~
- <input type="radio" value="A" name="3" />A 10 [! X/ P! s' O [5 e; N
- <input type="radio" value="B" name="3"/>B 2 ! i! c* \2 V7 B- P) K E
- <input type="radio" value="C" name="3"/>C 33 F% D8 f- p2 {3 H; z' d
- <input type="radio" value="D" name="3"/>D 无数+ l; R, Q7 k% T0 p1 _+ o# E
- </div>( n o0 Y1 ^* S5 K4 b* F: g! `8 S
- <a href="http://www.52itstyle.top/">传送门</a>
" h$ `: S" c) M( G" a& A - </body>
. c" Y8 k3 g4 ?. X - </html>
复制代码 本地存储JS封装:localstorage.js 不得不佩服此人的代码掉渣天。; Z* _3 l! N9 Y( y' J
- /**+ W- e, {* Z+ }& q
- * 注册命名空间
( z8 v5 x1 P8 u. h6 B6 z, L - * @param {String} fullNS 完整的命名空间字符串,如qui.dialog1 t" d& m |' }9 C* x
- * @param {Boolean} isIgnorSelf 是否忽略自己,默认为false,不忽略0 P! v1 f( \; E" ]# o
- * @author zhaoxianlie(xianliezhao@foxmail.com)
7 Y) v2 C1 w. y6 e4 R9 M - * @example, q: P+ }+ J8 P* M
- * window.registNS("QingFeed.Text.Bold");6 Z2 T2 J& n5 Q- c9 }" w1 C) s
- */
9 u, L5 ]6 K1 f, Z8 k4 R) s/ S2 Z - window.registNS = function(fullNS,isIgnorSelf){
' ~( I7 c* t/ W - //命名空间合法性校验依据
! @8 Q4 d" J3 n+ L' m' q6 e4 X - var reg = /^[_$a-z]+[_$a-z0-9]*/i;" e/ ?0 J9 Y: g- U
-
6 Z" y; W- G' x* | - // 将命名空间切成N部分, 比如baidu.libs.Firefox等& H# O/ d4 v; S% e. y
- var nsArray = fullNS.split('.');
2 H; F% A+ i0 y, ?" y1 I - var sEval = "";6 N. N# z. `% V$ _# H
- var sNS = ""; B# X1 L; Q& Y+ B! q, W l9 {
- var n = isIgnorSelf ? nsArray.length - 1 : nsArray.length;
2 ~% x; h! M. T - for (var i = 0; i < n; i++){' U# } V" o* e' q& M' N# }" O
- //命名空间合法性校验+ G) B0 t9 [! X+ _0 {# l( t
- if(!reg.test(nsArray[i])) {& T1 T# D P. g6 O3 u
- throw new Error("Invalid namespace:" + nsArray[i] + "");
. t4 K8 J/ I: i' y/ g - return ;
$ v2 f9 _$ ]# U8 d( R - }' P: I, {3 D; K1 ~
- if (i != 0) sNS += ".";' h- i' ~( h3 l6 c( i; t- L
- sNS += nsArray[i];9 X" k4 y" x, |7 W3 n
- // 依次创建构造命名空间对象(假如不存在的话)的语句
6 h# l$ q& G1 n7 s - sEval += "if(typeof(" + sNS + ")=='undefined') " + sNS + "=new Object();else " + sNS + ";";6 t2 F4 M* _% i( H
- }& [# g% U9 }( B
- //生成命名空间0 d( Z/ b6 d$ T3 M! {8 U
- if (sEval != "") {
, A* B$ I$ \2 z( u5 c - return eval(sEval);
" o2 j8 A5 S' O+ A - }
8 Q9 g3 Z* `4 G# u - return {};, F* T3 I: Y1 v# w- V$ w
- };2 K) Q% M T8 |) v
- ; n0 O5 X& Z% {+ E: b7 _- h
- 5 Y v; K4 u( m* o
- /**, S+ M9 [7 E# o- I8 m, z
- * 注册命名空间2 L Z) D7 p, f2 _- |
- */' x# o& k) x& x) ?- O% W
- window.registNS('qext');
# [7 E- k+ |& |2 Y4 n
0 @2 l$ q9 t4 t7 W* ?2 F+ d- /**
+ |& D* E+ m+ p9 g2 n% [( I& H* r - * @class qext.LocalStorage+ l$ H- x/ w6 z" m0 N( `3 L
- * 跨浏览器的本地存储实现。高级浏览器使用localstorage,ie使用UserData。虽然说是本地存储,也请不要存储过大数据,最好不要大于64K.( h$ j2 Y' D2 c$ r9 S
- * 因为ie下UserData每页最大存储是64k。
# j. W1 H5 M2 H$ x4 O R; ^ - * @singleton- h7 n; b0 X& N! z$ T0 ~# n) C, Z9 Z
- * @author zhaoxianlie (xianliezhao@foxmail.com)
( N5 @8 q4 S9 j- O |8 [; i - */* C3 Z( [9 T2 O# U+ W7 f* U. F
- (function(){
: V I [5 P1 W* m, t) k. h - /**( @/ F! f9 L% Y2 r$ a7 }
- * 验证字符串是否合法的键名* L x2 D, `, i0 \6 V
- * @param {Object} key 待验证的key
S. U/ h! q3 N; C5 Y - * @return {Boolean} true:合法,false:不合法$ l3 z. d( O/ l* m* h$ c$ A# a# P2 R$ Y
- * @private. s0 c& n1 }5 A8 }" z! }& ?3 d
- */1 H q- |' j! l* J" d& X
- function _isValidKey(key) {
, q& D, d* _ e9 y - return (new RegExp("^[^\\x00-\\x20\\x7f\\(\\)<>@,;:\\\\\\"\\[\\]\\?=\\{\\}\\/\\u0080-\\uffff]+\x24")).test(key);
+ X9 Z# `! x( A8 v - }% I8 X# W$ v! g: v0 }4 M
- 9 {! s. V6 k9 L6 h* p, F2 _
- //所有的key7 `0 b* Z( c, Q8 W: c, E$ o
- var _clearAllKey = "_baidu.ALL.KEY_";7 x* t: i1 _9 E% d8 o4 h
- ! J( f" Y5 E" x. U1 C( e, K O
- /**7 X; W( {: B7 n
- * 创建并获取这个input:hidden实例3 O. N6 v, B# w+ u. R
- * @return {HTMLInputElement} input:hidden实例
1 O% t( E g: G* ^* r6 Q; L# I - * @private) B9 u5 Y: ?9 g3 g. x
- */
+ y" i2 i/ v: r V5 Q3 n( x - function _getInstance(){$ a5 I4 @+ _/ ^: @
- //把UserData绑定到input:hidden上
- Y& I# q/ X T) r/ l3 H. Q p - var _input = null;8 f% k: F3 @, ^
- //是的,不要惊讶,这里每次都会创建一个input:hidden并增加到DOM树种$ \! _, U+ A# j- D K2 \0 x
- //目的是避免数据被重复写入,提早造成“磁盘空间写满”的Exception
) s: x8 o+ R- G% q; v( `/ O - _input = document.createElement("input");
7 p( S! w8 c/ D - _input.type = "hidden";( j- s! [* h; a8 V* H( P! `* q! a
- _input.addBehavior("#default#userData");
4 y8 s5 }2 f. w6 _1 G - document.body.appendChild(_input); & f+ n, X* e4 o' b* u
- return _input;4 f5 x2 G2 m1 v' e% l' b' m$ R5 P3 J( A3 w
- }7 D' o' [- \6 X% W
-
! @: v# j1 O- [6 Q! s4 K# ~4 n2 d i - /**
$ `" t/ d- g# I - * 将数据通过UserData的方式保存到本地,文件名为:文件名为:config.key[1].xml
; \! c" q' X m' n) s - * @param {String} key 待存储数据的key,和config参数中的key是一样的
2 a- W: V! e* f2 F- I - * @param {Object} config 待存储数据相关配置
3 B: A Z, e. A- I! A, P- D - * @cofnig {String} key 待存储数据的key+ K0 k2 k2 r9 r6 U9 {; |! p4 B
- * @config {String} value 待存储数据的内容7 n$ J0 o6 Z1 j; N/ h: _1 Y
- * @config {String|Object} [expires] 数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间
: p+ u! c6 X* C6 X% {. P% T - * @private
M+ n3 Q$ p- f4 l; {3 w' E, W$ E - */
5 m/ ?) J% V$ Z+ C - function __setItem(key,config){3 l! ?6 G( n0 W/ e3 p2 Z2 i
- try {
6 o5 F* I: V' D: |4 q5 P; ^2 D, o1 Q - var input = _getInstance();0 s/ Y2 \; [5 e" O% H' ?
- //创建一个Storage对象
; X' [" C1 ^% [ - var storageInfo = config || {};
- \0 E) f* y; G( ] - //设置过期时间% G( y8 _- W# a: R: a
- if(storageInfo.expires) {
9 y" F* [( J2 ]$ d5 K Y! h4 X - var expires;
+ K1 p6 {8 R1 O, b9 h - //如果设置项里的expires为数字,则表示数据的能存活的毫秒数
! e G* I8 i* H: F. W$ k7 L% B - if ('number' == typeof storageInfo.expires) {
/ D# M, ], c" m( G8 S5 n9 }/ x - expires = new Date();4 A" x0 z$ d$ T7 Y
- expires.setTime(expires.getTime() + storageInfo.expires);* q3 F/ C' t: Y8 j- s1 B
- }
. E* e- |) d. F" W4 c8 N - input.expires = expires.toUTCString();
& d) ~) C5 \: C6 j5 I3 T - }# n* l8 T" r8 ^- Y9 o
-
2 T' ^9 y( H/ V2 X |& X - //存储数据
& Z& g* d9 M3 N6 n8 z { - input.setAttribute(storageInfo.key,storageInfo.value);6 T1 r% O; b+ G$ A) P
- //存储到本地文件,文件名为:storageInfo.key[1].xml2 n! k; R9 z- U j4 w. M
- input.save(storageInfo.key);$ x6 R" E* p5 A1 @ m- e ^
- } catch (e) {1 o) K; @) q6 D3 `$ ~/ ]* z" @+ [3 y
- }
' L* v( F* B, R; l8 K. i" u5 D- U - }
2 T$ n: b& G4 {) u) W6 q' _/ H - 2 j3 P: c8 c2 J7 c/ V7 R+ d$ i
- /**0 i6 M2 u* t! W
- * 将数据通过UserData的方式保存到本地,文件名为:文件名为:config.key[1].xml0 E; w7 X7 S) f
- * @param {String} key 待存储数据的key,和config参数中的key是一样的
, }" ^8 q0 b* a: B2 k& w& b! ] - * @param {Object} config 待存储数据相关配置! h7 t% V8 ^, d2 B3 A8 o
- * @cofnig {String} key 待存储数据的key# g, r# K( W8 Y* D/ I, A9 \ C
- * @config {String} value 待存储数据的内容( _# f" ]5 ^8 A: _
- * @config {String|Object} [expires] 数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间, g, Q. f! R/ n) W
- * @private1 X; q+ y2 w- k6 F/ c2 [$ v
- */
6 K5 O5 `: z& }- l - function _setItem(key,config){# W# n, B7 k& O& R) Z; X1 ?
- //保存有效内容
; k* E0 O6 N1 C - __setItem(key,config);
5 q# Q+ Y' G% D2 z/ p) s -
$ G3 v' D, T1 B. @: \+ o! q - //下面的代码用来记录当前保存的key,便于以后clearAll
/ ?: P* m6 N$ Z- I - var result = _getItem({key : _clearAllKey}); @' Q# z3 v+ W5 w
- if(result) {
& l R* C% E, n! d- ~: Y+ j - result = {( }, Q( j0 G Z6 u U# }
- key : _clearAllKey,$ |- w2 r' }, J4 G, \
- value : result
2 I$ w5 ]( ~2 j$ J - };
/ O6 b$ }( t9 u; t& i - } else {5 x, y$ W+ d: t8 l; n! K' J0 |" ?# T
- result = {
* K5 `0 S1 u6 W) D( V0 J% Y! ? - key : _clearAllKey,' Q4 I) c# _$ s; d/ o3 U; _
- value : ""
6 I3 m4 i, @/ g, s( q - };
h7 z5 K7 B7 V" v2 Q! H - }, }2 ?( E9 o8 N# J$ H3 r( W
-
: Y$ S. _9 ~& I* [( v; P' M4 f. D - if(!(new RegExp("(^|\\|)" + key + "(\\||$)",'g')).test(result.value)) {
! W/ i& d$ d2 y3 M - result.value += "|" + key;7 Y7 B) [" O" Q2 W% O& Z
- //保存键$ i* e4 o3 b! C, Q* p
- __setItem(_clearAllKey,result); - e+ {( N* ^3 \
- }* p7 S# D) `6 _
- }7 y: x1 L# e8 a# A2 \
-
! h1 Y. c$ ^1 R: B! X' V! B3 D - /**
% J+ i$ t4 T8 I/ S& p# k - * 提取本地存储的数据8 s8 j6 }6 u6 [: g: j0 P4 N! h
- * @param {String} config 待获取的存储数据相关配置7 f- K( Z \6 o# u0 Z8 U8 \
- * @cofnig {String} key 待获取的数据的key
8 g( y s' c' q - * @return {String} 本地存储的数据,获取不到时返回null
6 C: t/ @4 \% u - * @example / J6 }9 n$ r. u6 q5 p$ |: [
- * qext.LocalStorage.get({3 ]- f' h* y% W) t+ L
- * key : "username"
2 j* z w1 U- X - * });
2 q# e+ s! i# `( q# ?/ O' A6 D7 I- v - * @private; T2 W5 a9 }# g+ T6 q% T
- */+ R) f% V2 x) p; G! w0 M' z
- function _getItem(config){
# r2 O7 q( P$ X+ s8 W8 I - try {
* v" m, R, \* p( v$ z4 m* I - var input = _getInstance();! ?/ K1 `) e: Q+ N1 N6 \# }
- //载入本地文件,文件名为:config.key[1].xml1 W& o( w. Q) b0 A/ t5 E* {
- input.load(config.key);
0 z+ a/ ^ N1 Q6 L; o/ {+ O$ [. |+ R - //取得数据2 j# ?+ T9 g6 F+ u- }
- return input.getAttribute(config.key) || null;$ u, K9 i% y3 c6 D1 {' P" F3 W, S! h
- } catch (e) {5 o4 O, {8 c! @" S& C
- return null; 0 }, L$ F5 B0 f) K4 r8 N6 k
- }
' C/ a8 J6 M5 \# H- a - }; v+ A* D/ Z. X
-
% t) x3 n8 V6 {' h' w7 A - /**
3 \7 |& c8 g7 v0 u4 X - * 移除某项存储数据" I0 Q% M/ g$ ]2 J* b0 s
- * @param {Object} config 配置参数
1 L& I$ s- q7 F V/ @4 h - * @cofnig {String} key 待存储数据的key
8 v' ~5 m" K; G2 v; H4 ]+ V& H( d! M - * @private
0 u P9 @$ W- @1 j* b - */8 M1 h9 a5 p/ u* ]( {
- function _removeItem(config){. r! O( W8 [0 K( W& w
- try {
7 l9 @2 N$ R6 L; q7 w8 u+ s - var input = _getInstance();
% M9 [, Y7 H( t5 G* q, t - //载入存储区块
- L; z6 i" N: P( ~9 Q1 T - input.load(config.key);% \5 ~6 t* `/ D9 J+ A
- //移除配置项
/ F$ P0 d. ` D" k, a+ S" W - input.removeAttribute(config.key);
. [2 X: X5 V$ T, q - //强制使其过期0 Z$ J: T' V9 m
- var expires = new Date();/ P3 U2 ^7 N2 k1 B) C9 X( |
- expires.setTime(expires.getTime() - 1);
. G r2 ~6 x: ~6 C - input.expires = expires.toUTCString();
* W( x; |' z: p: u% v - input.save(config.key);0 E% N: ~" D; l8 ~. Q/ g
-
( e( [) H4 u1 n3 Q1 B - //从allkey中删除当前key
- O2 L* Z( Z# s0 s& {) y - //下面的代码用来记录当前保存的key,便于以后clearAll
+ w# _3 I' L- n+ f2 [7 O2 d9 \ - var result = _getItem({key : _clearAllKey});! w, ~: p; e+ C4 n
- if(result) {
+ }8 `: D4 X0 a: G* {, o4 P - result = result.replace(new RegExp("(^|\\|)" + config.key + "(\\||$)",'g'),'');
7 W: v$ W) W* ^, _ - result = {
+ K+ \4 G. E( V( q( q# G) C; c - key : _clearAllKey,% X2 o/ ]! _' n! G$ {) ~
- value : result
" f, ^" c! g: z - };. b5 A" Q+ @% D" Q# M
- //保存键
) ^; Y' O; v( }( y" V/ s+ X - __setItem(_clearAllKey,result); / }6 E7 N3 x& C; k; k
- }
* z( Y& E+ z& o" A! h! c9 J, Q - 3 Q; i, { l6 y4 w# ]' q
- } catch (e) {4 w, U# H$ l4 a; t: I5 e0 N3 ~! P
- }0 F3 Y# l& J }" l
- } W1 N& N+ k! J9 X8 R! P
-
8 v7 P, n# A' `+ \ - //移除所有的本地数据
: Q3 N* R+ x8 P$ X, ?, }* b - function _clearAll(){1 X4 S" y8 N+ N
- result = _getItem({key : _clearAllKey});* @6 _/ O, B% y" }* F8 v1 O
- if(result) {
3 d9 Z% J+ \" Y' L0 O' v - var allKeys = result.split("|");
$ j: D. m. J; j! b - var count = allKeys.length;7 {6 g" J: _, n. B
- for(var i = 0;i < count;i++){
& R+ i; ]- J& L; H3 t, G+ r - if(!!allKeys[i]) {: N& Z" O0 b. ~) U7 T- ^$ ?& }+ Y# {4 r4 J
- _removeItem({key:allKeys[i]});
# v0 x l. G6 k4 J8 _! z! G - }
2 J0 R- \4 V! R - }
( p/ W/ I2 X3 v6 E - }6 J0 [+ C8 b" D/ I4 X
- }
( d& S$ T5 f' }) O% F$ o -
) A3 v/ H/ m. c. P -
$ e1 p$ ]; f" m g - /**, G5 ]5 h8 u# T' {- ^1 C
- * 获取所有的本地存储数据对应的key( `0 D f8 Z* \2 J5 P# C
- * @return {Array} 所有的key% S1 y, h- @) \+ o5 O
- * @private , V1 Z( Z! g8 W# ^$ z1 V. {
- */% Z4 w; K1 E. M5 O
- function _getAllKeys(){
( a2 g/ ~6 {$ I, Z0 a0 m& b - var result = [];" u+ u8 L) v1 M( _5 u2 P: h
- var keys = _getItem({key : _clearAllKey}); U& s! R9 ` M* ?& T# ?! [
- if(keys) {
( y) \5 X7 n8 b3 H - keys = keys.split('|');
8 U; \9 A1 }& P# Y - for(var i = 0,len = keys.length;i < len;i++){2 ~- [' F# f9 F" z- M/ h/ c) U }
- if(!!keys[i]) {
6 \+ o4 z5 z9 x1 `( a0 n - result.push(keys[i]);
# o( i2 o2 u' O4 w$ f' V - }
: q; c9 \: ^/ p# E8 q - }
- G0 U, P7 i Z9 o4 x - }. W4 l" d/ j6 g8 t! I; z
- return result ;
, z/ ?1 `$ b7 D5 ^7 a( N. O9 b - }
" a) a) B6 ?- j% R- @& y - 6 ?, R4 B# T8 g7 `' n; ~
- /**5 H$ ?- r' t. o* ?) W- E {
- * 判断当前浏览器是否支持本地存储:window.localStorage
& X- l* f) R: X - * @return {Boolean} true:支持;false:不支持
* L; P8 d0 K( p, M - * @remark 支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
- o1 U, s( w& ^7 i2 [7 g7 ?1 k" u - * @private$ Q* ?/ b" q. R9 Y
- */
8 W9 Y P ?' v0 [9 h8 V* O2 L+ u - var _isSupportLocalStorage = (('localStorage' in window) && (window['localStorage'] !== null)),
; f' ]* z; k& {$ y0 { - _isSupportUserData = !!jQuery.browser.ie;
/ w* A: W& I c" U& q3 Z - - G7 o0 t6 [5 j2 d+ u" H8 d4 D
- qext.LocalStorage = {( z1 ?+ |* e4 G) [8 S
- /**
+ R% K% i- j# g - * 如果支持本地存储,返回true;否则返回false
* l5 p, x' Y3 h8 G3 \6 }* I( | - * @type Boolean9 o+ |+ J1 w" @
- */
! z! G3 a/ M$ l - isAvailable : _isSupportLocalStorage || _isSupportUserData,
( d$ l1 |3 F1 T -
3 W- z. n( W0 h- _. V( ~/ ]9 C - /**
8 v/ A' H: z; `2 F* b - * 将数据进行本地存储(只能存储字符串信息)' O, p4 d+ |7 ?2 N7 w) b' ]4 G
- * <pre><code>
5 s$ O9 T3 `9 a3 a - * //保存单个对象4 j8 b1 b" I; t* e
- * qext.LocalStorage.set({
8 B! }8 C" G0 s: r1 `+ w - * key : "username",) l" n k& K; `+ b
- * value : "baiduie",
$ v T7 x e1 T% ? - * expires : 3600 * 10001 h- T8 Y( R# L# x+ M
- * });
6 V3 `+ d; n' i& I+ D9 ^2 a! {! K - * //保存对个对象7 v3 u5 l' _! A _) {* x0 H! D
- * qext.LocalStorage.set([{
+ k6 J! G2 C. f; V6 q5 m( j - * key : "username",9 S/ W; G+ c( z1 ?$ \1 i8 {
- * value : "baiduie"," n; B$ H! |* M/ n& I
- * expires : 3600 * 1000% {6 _, h) @8 S
- * },{
7 @7 v2 w, y$ k6 `( N - * key : "password",
* Y2 v( p6 }! F/ P, F( o/ g* A - * value : "zxlie",( R9 ^3 _$ _& T* r
- * expires : 3600 * 1000
9 {$ `: ]! Q' x& o - * }]);; x J* F2 r) G3 U7 e, p
- * </code></pre>
9 B2 A! Q6 u& G! S - * @param {Object} obj 待存储数据相关配置,可以是单个JSON对象,也可以是由多个JSON对象组成的数组
. N# V. S% m7 u5 z# w - * <ul>9 L& J6 L7 A+ z+ Q1 T2 `! R. {# J
- * <li><b>key</b> : String <div class="sub-desc">待存储数据的key,务必将key值起的复杂一些,如:baidu.username</div></li>
+ c& q* A" ?, J# @2 r- s - * <li><b>value</b> : String <div class="sub-desc">待存储数据的内容</div></li>
1 P0 X) c- a/ B% q# u( U! V5 q - * <li><b>expires</b> : String/Object (Optional)<div class="sub-desc">数据的过期时间,可以是数字,单位是毫秒;也可以是日期对象,表示过期时间</div></li> d% Y) ~' _. O- K$ k/ O) ^+ f
- * </ul>
6 l T; ^9 I3 E - */3 N2 @4 [) ^& Q+ G9 z) r4 c
- set : function(obj){
& E1 s7 p% }' u& L5 D - //保存单个对象& k' Y* t4 R) B+ ]) C9 G/ h, [( \
- var _set_ = function(config){- p( M& D- f% X/ x4 F
- //key校验
$ ~4 u1 _: G& n) b4 n# N" R7 R( c - if(!_isValidKey(config.key)) {return;}
* R9 E* @3 u! `
. G4 C6 f0 F: B, l- //待存储的数据/ p1 \/ o# }. M8 b! r% R
- var storageInfo = config || {};
% A5 {. @. n! d1 Z- p8 ]& t -
1 B* }3 J5 `( S% |+ a% } - //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
$ Z! {# v4 ?, \: G$ m - if(_isSupportLocalStorage) {
8 G8 ^2 y# V: E" v; }* K2 z - window.localStorage.setItem(storageInfo.key,storageInfo.value); @( O" V) }% v2 x* m3 P
- if(config.expires) {
! G1 k% ~* S/ o" m1 N- B3 o) u8 g* m - var expires;
+ Z7 h* H+ o' k - //如果设置项里的expires为数字,则表示数据的能存活的毫秒数2 F8 w* K( ]! V2 J/ m) W* b
- if ('number' == typeof storageInfo.expires) {
9 Y; E% u8 |; R W' T - expires = new Date();8 z- H, z% j a" d% H) `
- expires.setTime(expires.getTime() + storageInfo.expires);
! ^, y+ X4 r8 p z( E( W' ~1 u - }; I0 I! g3 d6 |: [' o( J! e
0 j; i" ]5 N* v/ Y% h- window.localStorage.setItem(storageInfo.key + ".expires",expires);; k6 \1 z; k& o
- }$ c' d; S+ b$ t3 t5 n: E" Z
- } else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式
' T) P3 p8 W# h7 Q2 W - _setItem(config.key,storageInfo);
. d8 l9 I( l; D; Q6 x - }
$ m# b) @, G9 |9 \3 F - };. |* ]1 E& x6 ?3 c8 U# C/ J
$ D: M# }) J: u+ Y/ n- //判断传入的参数是否为数组
0 U _ x: A. i S - if(obj && obj.constructor === Array && obj instanceof Array){
3 Y' Q9 G7 I. _& e0 s0 R0 B4 t - for(var i = 0,len = obj.length;i < len;i++){
, l6 q+ A& q/ E! A - _set_(obj[i]);2 q6 X4 w* z4 u& X# a8 G: I/ l
- }
3 o% }: D& U+ F. ]# v) K - }else if(obj){/ c8 X" a# Y- [( {; Z* y
- _set_(obj);1 j6 F4 o" Y1 ]. [/ s- _! ^
- }
( I8 R) ]# Y: G* L" B4 A# } K5 ~ - },
0 x; `) W3 D" ` G4 ?. [ - . K* U/ N9 N8 p. I# q
- /**- s! I. K' u' _4 |, }; u r
- * 提取本地存储的数据
, x2 ?3 w4 a9 W$ Y! V' D2 z/ f; B - * <pre><code>
/ e6 a. T# y' a3 }8 Z# W - * //获取某一个本地存储,返回值为:{key:"",value:"",expires:""},未取到值时返回值为:null. F2 @1 E' G5 n5 Y" W
- * var rst = qext.LocalStorage.get({
/ [$ h8 _) @, N9 V* c - * key : "username"5 Z- l' V0 `0 t' ^3 C. d7 S
- * });
0 Z/ {: `9 j. j. y* q - * //获取多个本地存储,返回值为:["","",""],未取到值时返回值为:[null,null,null]
3 P4 j7 B, O$ P' n% @* f - * qext.LocalStorage.get([{7 b6 }6 w1 Q% G0 H
- * key : "username"- m1 |" D) f1 }5 k4 V- [0 {
- * },{
) o/ h3 f) C$ L; J/ m- E* ~ - * key : "password"
0 B7 S2 t& p! p) N. w9 ^ - * },{
# r( I7 q6 y4 q' r6 j& i* { - * key : "sex"8 \% J3 l6 @! E3 }
- * }]);
5 E0 C5 z5 B3 G D9 ] c( T - * </code></pre>
0 S2 [$ C! ^* J - * @param {String} obj 待获取的存储数据相关配置,支持单个对象传入,同样也支持多个对象封装的数组格式, O! e4 [' M( s, a! `1 b
- * @config {String} key 待存储数据的key
8 C. u" @6 w9 _( m# o: S, t - * @return {String} 本地存储的数据,传入为单个对象时,返回单个对象,获取不到时返回null;传入为数组时,返回为数组
" E; ^& y/ V4 q - */& ~2 p9 P7 w( S9 r' |
- get : function(obj){/ P6 r! Y9 R6 Z0 n& k2 m5 v4 O
- //获取某一个本地存储
5 s# p, a4 T+ \* z* D - var _get_ = function(config){1 g5 ?% r/ E9 q! i# m& M8 r& A
- //结果
9 i/ L r( \- F5 w r% o" H R) X - var result = null;& v* ^3 A e- b. }' ]
- if(typeof config === "string") config = {key : config};" @- [% B6 B- R9 l. X
- //key校验8 C, ~) r: H) W! W" \& ]
- if(!_isValidKey(config.key)) {return result;}+ r+ Z3 V, l+ J
-
4 I ~+ K# D0 E2 v7 B - //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+! w7 c( Y u8 `+ V& D0 X3 R
- if(_isSupportLocalStorage) {
1 G1 D" c* {, q4 G: P! n - result = window.localStorage.getItem(config.key);
0 G; q, q" ?, x s4 G+ w - //过期时间判断,如果过期了,则移除该项# j f5 Q e0 C! o" Z- p% }
- if(result) {# \( [ ^ V" e! q- ^. Z! A
- var expires = window.localStorage.getItem(config.key + ".expires");' L p" g" m" a* G: x. u
- result = {6 ?/ w; k9 o4 H4 W* ]# l
- value : result,
$ T6 O0 N+ l; a2 ?' z j; r - expires : expires ? new Date(expires) : null
. X) {( o# w- X8 h1 r$ @ - };
, {) e p+ T; o - if(result && result.expires && result.expires < new Date()) {
% v6 f4 v! i4 x1 V- l& p' E - result = null;8 `' f6 r% O" }& B' A
- window.localStorage.removeItem(config.key);! m! Q; e) g/ J
- window.localStorage.removeItem(config.key + ".expires");
- Z3 s' J0 ?. T/ G' y - }
4 B4 t! @ O$ J2 n - }
6 |7 g, H9 H) ]6 Y# C$ r" i( O - } else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式0 f" X! L, y# d4 H* E: b
- //这里不用单独判断其expires,因为UserData本身具有这个判断
5 X4 ?1 Q5 o* L' A: s: { - result = _getItem(config);
, g" B: E# q- a& S5 `1 p9 Y - if(result) {
C; S! v5 b' s+ r" R2 I# @! P/ l8 m - result = { value : result };
0 v |4 l+ N1 z9 V3 b* k - }
! y/ u- N+ ?1 q6 H - }2 L5 J( b- C5 e4 L4 V
- * X m$ J/ n+ J- Y& A% w
- return result ? result.value : null;8 a7 f) p9 S) s! s
- };* F8 D, z9 s' M
-
* B* N5 f" q% g9 p9 D1 t2 C# D2 t - var rst = null;
- H- |: [- r1 [5 c! }1 b# o! ^ - //判断传入的参数是否为数组. u0 |! G5 |$ N( I
- if(obj && obj.constructor === Array && obj instanceof Array){
, `4 S& }9 l( }& s - rst = [];
/ d: l4 c7 R; H6 ? - for(var i = 0,len = obj.length;i < len;i++){
4 b3 i$ W3 G, r- ~6 x, l+ o - rst.push(_get_(obj[i]));% [ m& J9 e' R% ~( T5 Z2 u
- }9 b; G8 Y y( c" D8 }
- }else if(obj){4 n1 X2 ?' k$ t8 _) t" U3 P
- rst = _get_(obj);
: b, T2 m2 N( L# y - }1 E6 i! e+ h' P8 B
- return rst;4 s( q6 R3 ^ {% s# n: ^, D
- },, g$ ?- ^; z- s- o5 `9 ?
- 4 M. S* q0 Z$ d# @
- /**. W9 M' p/ R/ T
- * 移除某一项本地存储的数据# Q5 Y" B4 c4 L
- * <pre><code>* n$ p* b, N# A! W' V- O5 D# s
- * //删除一个本地存储项& _1 q# o( k: d
- * qext.LocalStorage.remove({+ K. _7 c3 W g7 M4 K! ?/ F
- * key : "username"
9 Z2 g- Y- k: f7 q# l, E - * });& X4 q. t; U( o) x* }, ^
- * //删除多个本地存储项目 *1 q3 S7 S! b, ]% a5 ?' G
- * qext.LocalStorage.remove([{
2 E8 U D4 F; \+ B% M$ s+ R - * key : "username"
1 s: ^ j& r7 L, d8 Y - * },{
3 U: e* e8 w% ?2 ^ - * key : "password"
( J: }! K+ K' a% I; [* `( ~2 r5 j7 N - * },{
, P) c- R4 X5 J) M' a - * key : "sex"/ u, A: j& m5 q" [9 t# Z) W
- * }]);3 F4 b- |) Y! `+ D( m' ?- q9 l
- * </code></pre>
& p! \* L0 h/ g7 ^/ O1 ` - * @param {String} obj 待移除的存储数据相关配置,支持移除某一个本地存储,也支持数组形式的批量移除( J7 I( j1 m, T9 \3 N) d
- * @config {String} key 待移除数据的key
% `$ P, |) F- H# Y* Z( u7 M - * @return 无
7 N$ z$ M$ G B' j - */0 o% U" s6 j4 @# X+ t0 w7 n
- remove : function(obj){$ O+ V) v: h3 e" s' a k
- //移除某一项本地存储的数据
8 o5 f% q% V$ m ?* E" b; a - var _remove_ = function(config){0 ^" I! K) W- b5 j
- //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
p% ~. @' S( D - if(_isSupportLocalStorage) {
, c9 R' Q7 i, r9 l4 A - window.localStorage.removeItem(config.key);
" X) L$ p# t5 ? S$ r - window.localStorage.removeItem(config.key + ".expires");- A. f9 \1 s; r5 y6 F
- } else if(_isSupportUserData){ //IE7及以下版本,采用UserData方式! R$ ^2 V/ f8 U2 A; o
- _removeItem(config);
3 x* g, d0 h1 l$ ?" V4 M, | - }7 f& n+ [- k; [ a
- };7 I/ G+ t! ~$ i, ^! y# `: [
-
; L$ Z: i& l( Z! b& s - //判断传入的参数是否为数组
- y( c$ J! M7 o& e! `7 K+ P8 b - if(obj && obj.constructor === Array && obj instanceof Array){4 \' X, }4 t8 {" ~- B. A2 |2 Y+ b
- for(var i = 0,len = obj.length;i < len;i++){1 w' X5 J2 F6 X' q% ?' f: M' G
- _remove_(obj[i]);
a& F3 y5 j. e' I' s- v! @ - }
% h, ^3 n$ E) N/ _6 D" j - }else if(obj){9 s7 @; N9 a o
- _remove_(obj);) P5 V8 {+ j9 x7 z' Z7 }
- }2 _) c( D l9 v
- },
, x3 ?. }: x1 A -
, g( s; C, G h: h; c - /**
2 {0 F' G! F l5 a; J7 J% i) L - * 清除所有本地存储的数据2 g- M7 F1 [9 |3 Y L7 ?
- * <pre><code>
: {3 Y3 o: E% Q5 [ - * qext.LocalStorage.clearAll();
: ^6 C/ y8 g/ r1 Q6 y - * </code></pre>
; n$ [! u( I( U; r - */; n X, z0 f* {/ P- r' |7 P
- clearAll : function(){
& t! l) D3 z* X2 u9 p - //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
4 \! k( u- P0 |( C' M! x; S9 a - if(_isSupportLocalStorage) {
) Y5 |+ u: z+ v! Z* N% H, z - window.localStorage.clear();
: ]& o! q% b6 h" n3 { - } else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式; c1 n/ C! h7 E) ^% i" P
- _clearAll();; w/ {% j, N7 P! n; P
- } X* k9 n9 h, I ?' r0 E
- },4 R/ b/ u X4 i4 l
-
( \! t. t5 n4 L- W$ g) K* @% K - //保存单个对象到本地# { G: x* J) [; }7 i% T
- save:function(StudentID,ExamID,QuestionID,ExamAnswer){
) G" e/ y& D" a) v+ m, l" ^ - qext.LocalStorage.set({
* ^- K- ^9 A7 ~( @9 r - key : StudentID+ExamID+QuestionID,, z9 P$ h" }! I
- value : "{ StudentID’: ‘"+StudentID+"’, ‘ExamID’: ‘"+ExamID+"’, ‘QuestionID’: ‘"+QuestionID+"’,‘ExamAnswer’: ‘"+ExamAnswer+"’}",
! v3 T% G1 g% u# U q- q3 k, G - expires : 3600 * 1000 /*单位:ms*/$ H0 A' N* j# Y4 o
- });
8 P0 p0 o! g( X" m2 m1 M4 v" _ - },
. Q4 |, K" \1 W0 r: P - /**
( K: I& a4 K& s% R9 T - * 获取所有的本地存储数据对应的key
4 d2 Y' ?, h- t7 J - * <pre><code>
0 C) N M. |$ }- i! b - * var keys = qext.LocalStorage.getAllKeys();
# p0 a3 m1 T3 T* W5 R2 v2 w - * </code></pre>
( p+ Q% G/ G$ J, m* K S2 R: X, z - * @return {Array} 所有的key
$ M1 O/ t3 }% j4 j4 C2 M2 J4 s$ q - */
5 h( s. i) g4 Y - getAllKeys : function(){
0 u% i' h/ w9 H& [+ S4 R - var result = [];
& Q5 F( O- V# Y. y6 ` p3 @/ O3 n - //支持本地存储的浏览器:IE8+、Firefox3.0+、Opera10.5+、Chrome4.0+、Safari4.0+、iPhone2.0+、Andrioid2.0+
% _- {; G# h5 K7 x - if(_isSupportLocalStorage) {
- |1 ?/ ^$ m! [/ k x0 }$ J - var key;
% V$ O5 O/ b' n, \0 }& z1 ?, s - for(var i = 0,len = window.localStorage.length;i < len;i++){( Z5 O' y$ {2 o
- key = window.localStorage.key(i);9 L; n7 l0 a8 d$ e4 n* E. E
- if(!/.+\.expires$/.test(key)) {
0 m0 e2 w# w9 Y$ b: _3 H% ]1 c - result.push(key);
$ C1 l4 z, o# j% g3 P1 q- r5 |$ H - }
3 P0 L( w7 b- V - }
) h5 n/ d3 D9 i6 b4 ^! ^1 l - } else if(_isSupportUserData) { //IE7及以下版本,采用UserData方式
! ?9 J9 S' U3 v - result = _getAllKeys();
' N* k! ^% g* j5 { - }( B5 Z# w% l( ?7 A& x
-
' Z4 v- }! O' E - return result;
) N8 X" q, q1 {3 f# Y$ I# j/ O' G7 Q - }
( C2 g; L3 |6 k; _8 ^5 n - };- \4 ]9 e; e, `6 v+ T- _
% U' C/ H- S! I0 E0 i9 D+ t- })();& z7 V+ S& ?5 M% I9 @* C
复制代码
: i* k+ [( m& Y+ w: V演示地址:http://www.52itstyle.top/localstorage/index.html
7 [, F. [) w Y' K# Y. e" k' c! I4 G+ r2 T* e7 w! h' r
HTML5 storage.zip
(46.03 KB, 下载次数: 0, 售价: 2 IT币)
. i3 d* d9 x+ `, i! {
" o' @% d2 X. u
! C- P7 z& L# U. j. b
Q$ o2 ~# f( T4 e
' E+ d$ {9 N+ q# D0 l# t, q2 ~7 u9 d- `/ f
|
|