![](http://static.javashuo.com/static/loading.gif)
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技術的產品則是隨時隨地使用化。