
H5本地存储有两个API,一个是Web Storage,还有一个是Web SQL。无论是哪个,都是基于JavaScript语言来使用,接下来我就教你怎么使用H5本地存储,本文篇幅较大,js代码较多,请耐心阅读。javascript
1、Web Storage教程
一、概述:html
对于Web Storage来讲,其实是Cookies存储的进化版。若是了解Cookie的人几乎一看Web Storage就会用,若是你历来没用过没了解过Cookie,不要紧,看了这篇文章照样轻松玩转Web Storage。首先,学习Web Storage只需背熟这句口诀:“两个接口,四个函数”。
前端
二、口诀:java
(1)两个接口:分别是localStorage和sessonStoragemysql
(2)四个函数:分别是setItem、getItem、removeItem和clear
程序员
三、localStorage:web
(1)特性:sql
域内安全、永久保存。即客户端或浏览器中来自同一域名的全部页面均可访问localStorage数据且数据除了删除不然永久保存,但客户端或浏览器之间的数据相互独立。数据库
(2)四个函数:编程
A. localStorage.setItem 存储数据信息到本地
B. localStorage.getItem 读取本地存储的信息
C. localStorage.removeItem 删除本地存储的信息
D. localStorage.clear 清空因此存储的信息
四、sessonStorage:
(1)特性:
会话控制、短时间保存。会话概念与服务器端的session概念类似,短时间保存指窗口或浏览器或客户端关闭后自动消除数据。
(2)四个函数:
A. sessionStorage.setItem 存储数据信息到本地
B. sessionStorage.getItem 读取本地存储的信息
C. sessionStorage.removeItem 删除本地存储的信息
D. sessionStorage.clear 清空因此存储的信息
五、四个函数的用法:
(1)localStorage.setItem(键名,键值)
在本地客户端存储一个字符串类型的数据,其中,第一个参数“键名”表明了该数据的标识符,而第二个参数“键值”为该数据自己。如:
localStorage.setItem("coffeeType", "mocha"); //存储键名为coffeeType和键值为mocha的数据到本地
localStorage.setItem("coffeePrice", "28"); //有了上一句作参考,这句意思你该理解了吧
(2)localStorage.getItem(键名)
读取已存储在本地的数据,经过键名做为参数读取出对应键名的数据。如:
var data = localStorage.getItem("coffeeType"); //读取对应键名为coffeeType的数据
(3)localStorage.removeItem(键名)
移除已存储在本地的数据,经过键名做为参数删除对应键名的数据。如:
localStorage.removeItem("coffeeType"); //从本地存储中移除键名为coffeeType的数据
(4)localStorage.clear()
移除本地存储全部数据。如:
localStorage.clear(); //保存着的"coffeePrice/28"键/值对也被移除了,全部本地数据拜拜
(5)另外,sessionStorage中的四个函数与以上localStorage类的函数用法基本一致,就再也不详解。
六、兼容问题:
有人会说本地存储是H5的新贵,可是对于老、旧的浏览器来讲怎么办?那就不用老古董浏览器呗,或者使用cookie做为替代。由于大多使用localStorage是用来存储字符串的,在其余编译型的语言看来,存储字符串能作些什么,但在javascript身上,旧大放光彩,能够存储JSON格式的字符串来扩展应用,能够存储类名变量值等等信息再经过eval()来感觉使用JS的快感。既然localStorage是存储字符串的,那么在老古董浏览器上,能够经过使用Cookies来作替代方案并作好域内安全。
2、Web Storage应用
一、基本使用:
咱们先把上面的四个函数整理一下,并加入一段验证代码用于检测本地的数据存储的存在状况。
( localStorage 使用测试 )
- <script type="text/javascript">
-
- localStorage.setItem("coffeeType", "mocha");
- localStorage.setItem("coffeePrice", "28");
-
- verify();
- localStorage.removeItem("coffeeType");
- verify();
- localStorage.clear();
- verify();
-
-
- function verify(){
- var type = localStorage.getItem("coffeeType");
- var price = localStorage.getItem("coffeePrice");
- type = type ? type : '不存在';
- price = price ? price : '不存在';
-
- alert( "coffeeType: " + type + "\n\n" + "coffeePrice: " + price );
- }
- </script>
若是上面代码执行后弹出框提示不存在的话,那么意味着本地不支持H5的 localStorage 本地存储。那么不支持怎么办,DON'T 担忧,能够写一段代码来兼容使用,请继续看下去。
二、兼容使用:
在写兼容代码前,再来讲一点关于Web Storage的内容,在Web Storage的两个类中,咱们比较经常使用的是localStorage类,至于session的话就交给后台去写吧。可是localStorage类在不支持H5的时候使用不了,因此咱们将localStorage的四个函数封装一下,使得当浏览器或客户端不兼容localStorage时自动切换到Cookies存储。
首先,要写好一个操做cookie的类和函数,将四个函数的名字和参数还有功能和localStorage保持一致。正好,《JavaScript权威指南》第五版里已经写好了一个cookieStorage代码,可是呢,这段代码有BUG的,和稍微与localStorage不一致,因此我修改了一下,花了点时间造下轮子,代码以下:
( cookieStorage.js )
- window.cookieStorage = (new (function(){
- var maxage = 60*60*24*1000;
- var path = '/';
-
- var cookie = getCookie();
-
- function getCookie(){
- var cookie = {};
- var all = document.cookie;
- if(all === "")
- return cookie;
- var list = all.split("; ");
- for(var i=0; i < list.length; i++){
- var cookies = list[i];
- var p = cookies.indexOf("=");
- var name = cookies.substring(0,p);
- var value = cookies.substring(p+1);
- value = decodeURIComponent(value);
- cookie[name] = value;
- }
- return cookie;
- }
-
- var keys = [];
- for(var key in cookie)
- keys.push(key);
-
- this.length = keys.length;
-
- this.key = function(n){
- if(n<0 || n >= keys.length)
- return null;
- return keys[n];
- };
-
- this.setItem = function(key, value){
- if(! (key in cookie)){
- keys.push(key);
- this.length++;
- }
-
- cookie[key] = value;
- var cookies = key + "=" +encodeURIComponent(value);
- if(maxage)
- cookies += "; max-age=" + maxage;
- if(path)
- cookies += "; path=" + path;
-
- document.cookie = cookies;
- };
-
- this.getItem = function(name){
- return cookie[name] || null;
- };
-
- this.removeItem = function(key){
- if(!(key in cookie))
- return;
-
- delete cookie[key];
-
- for(var i=0; i<keys.length; i++){
- if(keys[i] === key){
- keys.splice(i, 1);
- break;
- }
- }
- this.length--;
-
- document.cookie = key + "=; max-age=0";
- };
-
- this.clear = function(){
- for(var i=0; i<keys.length; i++)
- document.cookie = keys[i] + "; max-age=0";
- cookie = {};
- keys = [];
- this.length = 0;
- };
- })());
有了上面的cookieStorage函数,那就好办了,只需 把localStorage跟cookieStorage整合在一块儿 就完美了。
那么开始动手,新建一个myStorage.js文件,把上面的cookieStorage代码Copy进去,而后再开始写如下代码:
( myStorage.js )
- window.myStorage = (new (function(){
-
- var storage;
-
- if(window.localStorage){
- storage = localStorage;
- }
- else{
- storage = cookieStorage;
- }
-
- this.setItem = function(key, value){
- storage.setItem(key, value);
- };
-
- this.getItem = function(name){
- return storage.getItem(name);
- };
-
- this.removeItem = function(key){
- storage.removeItem(key);
- };
-
- this.clear = function(){
- storage.clear();
- };
- })());
上面的代码是myStorage.js,你能够直接Copy。把作好的myStorage.js文件引入到HTML文档后,用法就是跟localStorage的函数同样,不信你试试:
(1)myStorage.setItem(键名,键值)
在本地客户端存储一个字符串类型的数据,其中,第一个参数“键名”表明了该数据的标识符,而第二个参数“键值”为该数据自己。如:
myStorage.setItem("coffeeType", "mocha"); //存储键名为coffeeType和键值为mocha的数据到本地
myStorage.setItem("coffeePrice", "28"); //有了上一句作参考,这句意思你该理解了吧
(2)myStorage.getItem(键名)
读取已存储在本地的数据,经过键名做为参数读取出对应键名的数据。如:
var data = myStorage.getItem("coffeeType"); //读取对应键名为coffeeType的数据
(3)myStorage.removeItem(键名)
移除已存储在本地的数据,经过键名做为参数删除对应键名的数据。如:
myStorage.removeItem("coffeeType"); //从本地存储中移除键名为coffeeType的数据
(4)myStorage.clear()
移除本地存储全部数据。如:
myStorage.clear(); //保存着的"coffeePrice/28"键/值对也被移除了,全部本地数据拜拜
仔细一看,你会发现,localStorage中的local改为了my变成了myStorage,这个不得了啊,当客户的使用环境不支持H5的时候,这个小小的变脸"my"但是会切换成cookie,有那么点可能救你一命。不过为了更加保命,你能够造多一个轮子,当客户环境不支持H5又不支持cookie时,轮子会自动把数据上传到服务器来保存;若是客户支持cookie,可是有按期清除的习惯,那么你能够作一个轮子来控制cookie时间,并在有限时间内把数据备份到服务,等等等等,看你怎么发挥吧。
想省事的童鞋,能够直接点击下载myStorage.js.
H5本地存储中,除了包含了localStorage和sessionStorage的Web Storage外,还有一个小众的Web SQL,请看下文。
3、Web SQL教程
一、概述:
H5的本地存储中,其实localStorage并不算是很强大的存储,而Web SQL Database才是牛逼的存在,在浏览器或客户端直接能够实现一个本地的数据库应用,好比作一个我的的备忘录啊,注意,是我的,为何?由于世面上只有主流的浏览器实现了WebSQL功能,不少非主流并不兼容WebSQL,而且,所谓的主流只是编程开发人员眼中的主流,若是是用户平时本身使用的那些乱七八糟的浏览器,WebSQL简直是灾难啊!!!另外,浏览器间对WebSQL的支持并不是为规范,由于这个规范几年前被官方放弃了。还有一个WebSQL不可以普遍使用的缘由是,大量前端工程师不懂数据库也没有上进心或好奇心或空闲时间去研究和学会应用WebSQL,致使了开发人员逃避WebSQL和用户对WebSQL没有使用习惯和各种客户端对WebSQL兼容性良莠不齐等现象,是WebSQL不可以像服务器端的数据库那么普遍应用的主要缘由。
吐槽归吐槽,教程仍是要写的。先说学习口诀:“一个语言,三个函数”。
二、口诀:
(1)一个语言:无论是WebSQL仍是MySQL,SQL的语法必须掌握。SQL是一个结构化查询语言,说白就是用来查询数据的语言中是最天然、最简洁的。
(2)三个函数:分别是:
A. openDatabase 建立或打开一个本地的数据库对象
B. executeSql 执行SQL语句,在回调函数的参数中获取执行结果
C. transaction 处理事务,当一条语句执行失败的时候,以前的执行所有失效
三、SQL:
(1)概述:
如下只是把每一个功能对应的最基本的SQL语句过一遍。若是不会SQL的,仅作简单语法参考,有兴趣的童鞋须要找资料系统性地全面学习。
(2)建立数据表:
建立具备多个列,每一个列用于存放可不一样类型的数据。有列天然有行的概念,行表明一组数据,每组数据是当行对应的多个列的数据集合。
CREATE TABLE IF NOT EXISTS 表名(列名称1 数据类型, 列名称2 数据类型, 列名称N 数据类型)
(3)查询数据:
从某表中查询某行某列的数据或查询表中全部元素。
SELECT 列名称1,列名称2,列名称3 FROM 表名称 WHERE 某列名 = 某值
(4)插入数据:
向某表中插入行数据,行中每一个值对应列名。
INSERT INTO 表名(列名称1, 列名称2, 列名称N) VALUES (值1, 值2, 值N)
(5)更新数据:
更新某行中列的值。
UPDATE 表名 SET 列名称1=新值, 列名称2=新值, 列名称N=新值 WHERE 某列名 = 某值
(6)删除数据:
删除某行,不然删除全部数据。
DELETE FROM 表名 WHERE 列名称 = 值
四、Web SQL本地存储的三个函数:
(1)openDatabase (数据库名字, 数据库版本号, 显示名字, 数据库保存数据的大小, 回调函数(可选))
不过是否一脸懵逼,好奇怪是否是,参数还要写版本号,还有,显示名字什么鬼?不过,通过测试后,我都是直接这样写就是了(大小请本身定),以下:
var db = openDatabase("MyDatabase", "", "My Database", 1024*1024);
(2)executeSql(查询字符串, 用以替换查询字符串中问号的参数, 执行成功回调函数(可选), 执行失败回调函数(可选))
参数一天然是SQL语句,其中值数据可用?代替;参数二是SQL语句中?对应的值(很像PDO的预处理)。注意,executeSql不能单独使用,须要在事务transaction函数下使用。例子以下:
executeSql("CREATE TABLE IF NOT EXISTS MyData(name TEXT,message TEXT,time INTEGER)");
(3)transaction(包含事务内容的一个方法, 执行成功回调函数(可选), 执行失败回调函数(可选))
事务内容为一个或多个executeSql函数构成。这个函数很难用语言表达,因此请看例子:
db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS MyData(name TEXT,message TEXT,time INTEGER)", [], function(){ alert("create ok")});
tx.executeSql("SELECT * FROM MyData", [], function(){alert("select ok")});
tx.executeSql("DROP TABLE IF EXISTS MyData", [], function(){alert("drop ok")});
});
五、Web SQL的使用:
程序员最喜欢作的事情之一就是封装,将代码封装成本身喜欢的样子,而后在须要用到时会感谢当年封装好的类或函数不须要再造轮子就直接修改着用。因此,我也不例外,把openDatabase、executeSql、transaction三个核心函数封装成一个类。注意,这个类只是实现基本的功能,而且查询我没有写条件查询而是直接查询所有结果。对封装Web SQL有兴趣的童鞋能够研究一下如下代码:
(没兴趣的请忽略,跳到第四条:H5本地存储的框架程序)
( webSQL.js )
- var webSQL_create_handle = null;
- var webSQL_insert_handle = null;
- var webSQL_update_handle = null;
- var webSQL_delete_handle = null;
- var webSQL_select_handle = null;
- var webSQL_drop_handle = null;
-
- function webSQL(database="MyDatabase", datasize=1024*1024){
- this.db = openDatabase(database, "", "My Database", datasize);
- }
- webSQL.prototype={
-
-
- constructor: webSQL,
-
-
- create : function(table, allcol){
- var col = "";
- for(var i=0; i<allcol.length; i++){
- col += allcol[i];
-
- if(i !== allcol.length-1){
- col += ",";
- }
- }
- var sql = "CREATE TABLE IF NOT EXISTS "+table+"("+col+")";
- this.db.transaction(function(tx){
- tx.executeSql(sql,
- [],
- function(tx,rs){
- console.log(tx,"建立表成功!");
- if(webSQL_create_handle && typeof(webSQL_create_handle)=="function"){
- webSQL_create_handle();
- }
- },
- function(tx,error){
- console.log(error,"建立表失败!");
- }
- );
- });
- },
-
-
- drop : function(table){
- var sql = "DROP TABLE IF EXISTS "+table;
- this.db.transaction(function(tx){
- tx.executeSql(sql,
- [],
- function(tx,rs){
- console.log(tx,"删除表成功!");
- if(webSQL_drop_handle && typeof(webSQL_drop_handle)=="function"){
- webSQL_drop_handle();
- }
- },
- function(tx,error){
- console.log(error,"删除表失败!");
- }
- );
- });
- },
-
-
- insert : function(tableName, colNameArray, colValueArray){
- var allColName = "";
- var quesMark = "";
- for(var i=0; i<colNameArray.length; i++){
- if(colNameArray[i]){
- allColName += colNameArray[i];
- quesMark += "?";
- if(i !== colNameArray.length-1){
- allColName += ",";
- quesMark += ",";
- }
- }
- }
- var sql = "INSERT INTO "+tableName+"("+allColName+") VALUES ("+quesMark+")";
- this.db.transaction(function(tx){
- tx.executeSql(
- sql,
- colValueArray,
- function(tx,rs){
- console.log(tx,"插入数据成功!");
- if(webSQL_insert_handle && typeof(webSQL_insert_handle)=="function"){
- webSQL_insert_handle();
- }
- },
- function(tx,error){
- console.log(error,"插入数据失败!");
- }
- );
- });
- },
-
-
- update : function(tableName, colNameArray, colValueArray, whereColName=null, whereColValue=null, relation="&&", equal="="){
- var colAndValue = "";
- for(var i=0; i<colNameArray.length; i++){
- if(colNameArray[i]){
- colAndValue += (colNameArray[i] + "=?");
- if(i !== colNameArray.length-1){
- colAndValue += ",";
- }
- }
- }
- var whereSyntax = "";
- if(whereColName){
- for(var j=0; j<whereColName.length; j++){
- if(whereColName[j]){
- if(j === 0){
- whereSyntax += " WHERE ";
- }
- whereSyntax += (whereColName[j] + "" + equal + "?");
- if(j !== whereColName.length-1){
- whereSyntax += (" "+relation+" ");
- }
- }
- }
- }
- var fanalArray = new Array();
- for(var m=0; m<colValueArray.length; m++){
- if(colValueArray[m]){
- fanalArray.push(colValueArray[m]);
- }
- }
- if(whereColValue){
- for(var n=0; n<whereColValue.length; n++){
- if(whereColValue[n]){
- fanalArray.push(whereColValue[n]);
- }
- }
- }
- var sql = "UPDATE "+tableName+" SET "+colAndValue+""+whereSyntax;
- this.db.transaction(function(tx){
- tx.executeSql(
- sql,
- fanalArray,
- function(tx,rs){
- console.log(tx,"更新数据成功");
- if(webSQL_update_handle && typeof(webSQL_update_handle)=="function"){
- webSQL_update_handle();
- }
- },
- function(tx,error){
- console.log(error,"更新数据失败!");
- }
- );
- });
- },
-
-
- delete : function(tableName, whereColName=null, whereColValue=null, relation="&&", equal="="){
- var whereSyntax = "";
- if(whereColName){
- for(var j=0; j<whereColName.length; j++){
- if(whereColName[j]){
- if(j === 0){
- whereSyntax += " WHERE ";
- }
- whereSyntax += (whereColName[j] + "" + equal + "?");
- if(j !== whereColName.length-1){
- whereSyntax += (" "+relation+" ");
- }
- }
- }
- }
- var fanalColValue = new Array();
- for(var n=0; n<whereColValue.length; n++){
- if(whereColValue[n]){
- fanalColValue.push(whereColValue[n]);
- }
- }
- var sql = "DELETE FROM "+tableName+""+whereSyntax;
- this.db.transaction(function(tx){
- tx.executeSql(
- sql,
- fanalColValue,
- function(tx,rs){
- console.log(tx,"删除数据成功!");
- if(webSQL_delete_handle && typeof(webSQL_delete_handle)=="function"){
- webSQL_delete_handle();
- }
- },
- function(tx,error){
- console.log(error,"删除数据失败!");
- }
- );
- });
- },
-
-
- select : function(tableName){
- var sql = "SELECT * FROM "+tableName;
- console.log("db",this.db);
- this.db.transaction(function(tx){
- tx.executeSql(
- sql,
- [],
- function(tx,rs){
- for(var i=0; i<rs.rows.length; i++){
- console.log(rs.rows.item(i).name, rs.rows.item(i).value);
- }
- if(webSQL_select_handle && typeof(webSQL_select_handle)=="function"){
- webSQL_select_handle(rs.rows);
- }
- },
- function(tx,error){
- console.log(error,"查询失败");
- }
- );
- });
- }
- }
好长好长的代码,看起来很长很臭,其实这个类很是易用,首先我要把这个类保存在js文件,我命名为webSQL.js,而后须要把这个类引入到HTML文档中使用,下面就是这个类的使用方法:
( webSQL.js 使用测试 )
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>测试Web SQL数据库</title>
- </head>
- <body>
- <div id="msg">
- <b>Test测试Web SQL</b><br><br><br>
- </div>
-
- <script src="webSQL.js"></script>
-
- <script type="text/javascript">
-
- //自行根据需求,补充完整查询执行后的回调函数,注意有带参数,参数为查询结果
- webSQL_select_handle = function(rows){
- document.getElementById("msg").innerHTML += "正在读取数据<br><br>";
- for(var i=0; i<rows.length; i++){
- //rows为查询结果,【rows.item(数据行号)】可获得行数据,【rows.item(行号).字段名】可获得行数据中的列字段的数据
- document.getElementById("msg").innerHTML += ((i+1)+". name: "+rows.item(i).name + ", value: " + rows.item(i).value +"<br><br>");
- }
- };
-
- //自行根据需求,补充完整新建数据表后的执行回调函数
- webSQL_create_handle = function(){
- document.getElementById("msg").innerHTML += "正在建立数据表<br><br>";
- };
-
- //自行根据需求,补充完整插入数据后的执行回调函数
- webSQL_insert_handle = function(){
- document.getElementById("msg").innerHTML += "正在插入数据<br><br>";
- };
-
- //自行根据需求,补充完整更新数据后的执行回调函数
- webSQL_update_handle = function(){
- document.getElementById("msg").innerHTML += "正在更新数据<br><br>";
- };
-
- //自行根据需求,补充完整删除数据后的执行回调函数
- webSQL_delete_handle = function(){
- document.getElementById("msg").innerHTML += "正在删除数据<br><br>";
- };
-
- //自行根据需求,补充完整删除表后的执行回调函数
- webSQL_drop_handle = function(){
- document.getElementById("msg").innerHTML += "正在清空并删除数据表<br><br>";
- }
-
- //实例化webSQL类
- var db = new webSQL("MyDatabase");
-
- //新建一个表,带有两个字段,分别为name和value
- db.create("myTable", ["name", "value"]);
-
- //插入两个数据,分别是Coffe和me
- db.insert("myTable", ["name", "value"], ["Coffee", "me"]);
-
- //插入两个数据,分别是JavaScript和good
- db.insert("myTable", ["name", "value"], ["JavaScript", "good"]);
-
- //查询全部数据
- db.select("myTable");
-
- //更新数据,将name字段为Coffee的值更改成lhb
- db.update("myTable",["name"],["lhb"],["name"],["Coffee"]);
-
- //查询全部数据
- db.select("myTable");
-
- //删除name为lhb的数据
- db.delete("myTable",["name"],["lhb"]);
-
- //查询全部数据
- db.select("myTable");
-
- //删除表
- db.drop("myTable");
- </script>
- </body>
- </html>
用法很是简单是否是,直接往我写好的函数传参数便可,不过这段代码只在Chrome谷歌浏览器测试经过,其余浏览器没试过,不肯定是否兼容其余浏览器。
有须要webSQL.js库的,能够复制粘贴或点击这里下载,若是你须要很完整的SQL操做,请你参考着写或找找其余类库(网上好多大神有封装过WebSQL的),本文全部代码皆只为了供学习和参考,不适直接生产使用。
4、H5本地存储的框架程序(重点)
一、localStorage类高级应用:
因为并非全部浏览器都支持WebSQL,而localStorage有着不限量且长期保存在硬盘的特色,因此能够将localStorage再改造,改形成为具有有数据库特色的应用。想要localStorage能具有数据库这种类型的功能,那只能依靠JSON来成大事了。JSON是文本、是语言、是对象、是数组,只要跟JS配合,简直就是万能的(夸张了)!因为JSON实质上是字符串,因此经过localStorage存储在本地十分方便,可是JSON又能够经过JS转化为对象(现在几乎全部语言都能解析JSON),因此小小字符串能成就无限可能。只要有想象力,JSON + JavaScript有强大的行动力。
扯远了!咱们先来讲说JSON如何使用:首先,到JSON官网下载 json2.js 文件并引入到HTML中;而后使用 JSON.stringify(js对象) 函数将js对象转换成json字符串,或者使用 JSON.parse(json字符串) 函数将json字符串转换成js对象。是否是很抽象?直接看代码吧:
(JSON使用方法)
- <script src="json2.js"></script>
- <script type="text/javascript">
- var Obj = { name: 'Coffee', sex: 'man' }; //一个js对象
-
- var Json = JSON.stringify(Obj); //将js对象转换成json字符串
-
- var Js = JSON.parse(Json); //json字符串转换成js对象
- </script>
掌握了JSON的基本操做后,咱们就能够来实现一套方便的本地数据存储了。咱们先来分析一下,咱们不须要庞杂的SQL语句来解析咱们要对数据库作的操做,咱们只须要有一套API,直接传值调用便可。一个数据库须要创建空间来保存信息,咱们先假想一个空间是能够无限扩展的、动态调整其自身大小的,但每一个空间之间的值是不关联的,这个空间的概念相似传统的数据表。
因此,咱们须要一个主要管理空间的函数,这个函数主要功能是:存储着每一个空间的名字、能够建立新的空间、确保向空间插入数据时空间是存在的不然插入失败、能够随意删除空间。
有了空间的概念后,就须要有个管理空间内部的机器人,这个机器人所懂得的行动就像基本的SQL操做同样,具备增、删、查、改功能。
空间能够理解为一个容器,这个容器像一个数组,但这个数组的成员不是相同类型的、有各类各样风格的、有大有小的。这里成员的概念又像对象,每一个对象均可以不同。
有了以上的想法后,个人手指不受控制地跟着思路跑,结果给我写出了这么一个基于JSON的本地存储,这个是我最满意的代码之一了:
( localDB.js )
- if(! (myStorage && JSON)){
- alert("须要myStorage.js和json2.js两个文件");
- }
-
- window.localDB = (new (function(){
-
-
- this.createSpace = function(space_name){
-
- if( typeof(space_name)!=="string" ){
- console.log("space_name参数需为字符串");
- return false;
- }
-
- if(!myStorage.getItem("localSpaceDB")){
- var space_obj = [];
- var space_json = JSON.stringify(space_obj);
- myStorage.setItem("localSpaceDB", space_json);
-
- console.log("新建localSpaceDB成功");
- }
-
-
- var space_obj = JSON.parse(myStorage.getItem("localSpaceDB"));
-
-
- for(var i=0; i<space_obj.length; i++){
- if(space_obj[i].spaceName == space_name){
-
- console.log("已存在空间名"+space_name+",新建失败");
-
- return false;
- }
- }
-
-
- var new_obj = {
- spaceName : space_name
- };
- var old_space_obj = JSON.parse(myStorage.getItem("localSpaceDB"));
- old_space_obj.push( new_obj );
- var new_space_json = JSON.stringify(old_space_obj);
- myStorage.setItem("localSpaceDB", new_space_json);
-
-
- var data_obj = [];
- var data_json = JSON.stringify(data_obj);
- myStorage.setItem(space_name, data_json);
-
- console.log("新建"+space_name+"空间成功");
- return true;
- };
-
-
-
- this.deleteSpace = function(space_name){
- if( typeof(space_name)!=="string" ){
- console.log("space_name参数需为字符串");
- return false;
- }
-
- var isDelete = false;
-
- var delIndex = -1;
-
- if(myStorage.getItem("localSpaceDB")){
-
- var all_space_name_obj = JSON.parse(myStorage.getItem("localSpaceDB"));
-
- for(var i=0; i<all_space_name_obj.length; i++){
- if(all_space_name_obj[i].spaceName == space_name){
- isDelete = true;
- delIndex = i;
- }
- }
-
- if(isDelete === true && delIndex !== -1){
- all_space_name_obj.splice(delIndex, 1);
- var new_space_json = JSON.stringify(all_space_name_obj);
-
- myStorage.setItem("localSpaceDB", new_space_json);
-
- myStorage.removeItem(space_name);
-
- console.log("成功删除"+space_name+"空间");
- return true;
- }
- else{
- console.log("删除空间失败,不存在"+space_name+"空间");
- return false;
- }
- }
- };
-
-
- this.insert = function(space_name, obj_data){
-
- if(myStorage.getItem(space_name)){
-
- var all_data = JSON.parse(myStorage.getItem(space_name));
-
- all_data.push(obj_data);
- myStorage.setItem(space_name, JSON.stringify(all_data));
-
- console.log("已插入数据:"+obj_data+",全部数据以下:");
- console.dir(all_data);
- return true;
- }
- else{
- console.log("不存在"+space_name+"空间");
- return false;
- }
- };
-
-
-
- this.update = function(space_name, obj_origin, obj_replace){
-
- if(myStorage.getItem(space_name)){
-
- var objIndex = -1;
-
- var all_data = JSON.parse(myStorage.getItem(space_name));
-
- for(var i=all_data.length-1; i>=0; i--){
-
- if(JSON.stringify(all_data[i]) == JSON.stringify(obj_origin)){
- objIndex = i;
- }
- }
-
- if(objIndex !== -1){
- all_data.splice(objIndex, 1, obj_replace);
-
- myStorage.setItem(space_name, JSON.stringify(all_data));
-
- console.log("已更新数据:"+obj_origin+",全部数据以下:");
- console.dir(all_data);
- return true;
- }
- else{
- console.log("没有"+obj_origin+"对象");
- return false;
- }
- }
- else{
- console.log("不存在"+space_name+"空间");
- return false;
- }
- };
-
-
-
- this.delete = function(space_name, obj_data){
-
- if(myStorage.getItem(space_name)){
-
- var objIndex = -1;
-
- var all_data = JSON.parse(myStorage.getItem(space_name));
-
- for(var i=all_data.length-1; i>=0; i--){
-
- if(JSON.stringify(all_data[i]) == JSON.stringify(obj_data)){
- objIndex = i;
- }
- }
-
- if(objIndex !== -1){
- all_data.splice(objIndex, 1);
-
- myStorage.setItem(space_name, JSON.stringify(all_data));
-
- console.log("已删除数据:"+obj_data+",全部数据以下:");
- console.dir(all_data);
- return true;
- }
- else{
- console.log("没有"+obj_data+"对象");
- return false;
- }
- }
- else{
- console.log("不存在"+space_name+"空间");
- return false;
- }
- };
-
-
- this.select = function(space_name, select_value=" ", is_select_all=true){
- if(myStorage.getItem(space_name)){
-
- var select_result = [];
-
-
- function productObj(row, ob){
- return ({
- At : row,
- Obj : ob
- });
- };
-
-
- var all_data = JSON.parse(myStorage.getItem(space_name));
-
-
- if(select_value){
-
- if(is_select_all === true){
- for(var i=all_data.length-1; i>=0; i--){
-
- select_result.push(new productObj(i,all_data[i]));
- }
- }
- else{
-
- for(var i=all_data.length-1; i>=0; i--){
-
- if( typeof(all_data[i]) === typeof(select_value) ){
- if(JSON.stringify(all_data[i]) === JSON.stringify(select_value) ){
-
- select_result.push(new productObj(i,all_data[i]));
- }
- }
- else{
- if( typeof(all_data[i]) !== "number" ||
- typeof(all_data[i]) !== "boolean" ||
- typeof(all_data[i]) !== "string"
- ){
- for( var x in all_data[i]){
- if(typeof(all_data[i][x]) === typeof(select_value)){
- if(JSON.stringify(all_data[i][x]) === JSON.stringify(select_value) ){
-
- select_result.push(new productObj(i,all_data[i]));
- }
- }
- }
- }
- }
- }
- }
- }
- if(select_result.length>0){
- console.log("查询到结果");
- console.dir(select_result);
- }
- else{
- console.log("没查询到结果");
- }
-
-
- return select_result;
- }
- else{
- console.log("不存在"+space_name+"空间");
- return [];
- }
- };
-
- })());
至于上面的 localDB.js 的用法,很简单,我写了一个例子:
( localDB.js 使用测试 )
- <script src="myStorage.js"></script>
- <script src="json2.js"></script>
- <script src="localDB.js"></script>
-
- <script type="text/javascript">
-
- //建立一个叫Coffee存储空间
- localDB.createSpace("Coffee");
-
- //能够向Coffee插入任何类型的数据
- localDB.insert("Coffee", "mocha");
- localDB.insert("Coffee", {name:"cappuccino",price:28});
- localDB.insert("Coffee", false);
- localDB.insert("Coffee", [1,2,3]);
-
- //更新某个数据,第二个参数须要跟插入时对应的参数的值如出一辙
- localDB.update("Coffee", "mocha", "DB");
- localDB.update("Coffee", {name:"cappuccino",price:28}, {name:"latte",price:31})
-
- //按条件查询数据并返回结果数组,最多可按条件深度挖掘到空间的第三层数据,有兴趣的童鞋能够加个递归让它不停挖掘数据
- var some = localDB.select("Coffee","man");
- //不输入第2、三参数则查找空间中所有数据
- var all = localDB.select("Coffee");
-
- //删除空间中的数据,第二个参数须要跟插入时对应的参数值如出一辙
- localDB.delete("Coffee","DB");
- //删除Coffe空间,空间全部数据丢失
- localDB.deleteSpace("Coffee");
-
- </script>
二、localDB数据存储的相关概念:
(1)两个空间:
这里的空间是指空间管理器的功能,一个是createSpace函数用于按名建立一个存储空间,另外一个是deleteSpace函数是用于按名删除一个存储空间。
(2)四个操做:
这里的操做是指对某个空间所能执行的操做,第一个是insert操做能向空间插入任一类型的数据,第二个是update操做能用一个数据去替换空间的某个数据,第三个是delete操做能删除空间中某个数据,第四个是select操做能根据一个数据去查询空间中匹配的数据并返回一个存储着多个 { At:结果数组下标值, Obj:结果对象 } 对象的结果数组。
(3)对比:
比WebSQL简单多了有木有?原本我打算将local封装成使用SQL来操做的数据库,可是有三点理由阻止了个人冲动,第1、我没有时间(单纯完成这篇文章就花了我好几天空余时间);第2、网上已经有大神封装过了,那个复杂啊看得我以为再去封装不必了;第3、就算将localDB弄成SQL的操做,体验上也没有直接用WebSQL好。若是排除了以前使用数据库的惯性,只从js角度来看,WebSQL这样的用法彻底丢失了js的最大特性——动态,不采用SQL方案而选择JSON才符合JS的正统血液,只要不考虑性能问题,把性能的影响压缩到最小,基于JSON的H5本地存储才适合前端的环境,JS+JSON能诞生更多创造性的编程方法,同时H5才会愈来愈具有魅力和挑战。
三、localDB类的应用场景:
有了localDB类,能作什么?作的东西可多了,好比,在本地保存用户的帐号、密码、帐号信息,就能够避免同一个网站二次登录,或者避免了屡次请求重复的数据致使加大了服务器的负担,可定时根据序列号或md5值等等方案来同步本地与服务器的数据等等。总之,在H5本地存储领域,原生的localStorage是用得最普遍的,至于seesionStorage还不如服务器端语言用得方便实在,而webSQL就没必要说了,兼容性太差,开发起来太麻烦,而且有点鸡肋。因此,若是你想体验或使用H5存储,能够试用个人localDB,目的是经过使用我写的localDB来提供你一些思路,而后你能根据需求来打造属于你的H5本地存储函数。
有须要localDB.js的童鞋,请点击这里下载。
5、总结;
若是是作一个网站的话,大多仍是依赖着服务器,几乎全部数据都存储在服务器,大量的数值运算也在服务器,因此对于网站来讲,H5本地存储除了提升用户体验、增强本地应用功能以外,彷佛有点鸡肋和尴尬。可是,H5并非都用来作网站的,好比在游戏方面,H5本地存储提供了一个很好的存储功能,也就意味着H5所作的并不必定都是联网应用,它也能够是本地应用,没有网络照样玩得转起来,在没有网络的状况下,本地存储是一个必要的存在了。在NativeApp的开发趋于重度联网应用的状况下,WebApp正在悄悄兼顾并完善着起本地的使用,在将来谁会取代谁很差说,但发展趋势是原生软件更加依赖硬件的支持即软件硬件化,而H5技术的产品则是随时随地使用化。