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