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