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