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