在前端項目開發中,前端的本地存儲是必不可少的,今天小編就前端的本地存儲在項目中的使用詳細的介紹一下。前端本地存儲主要有:html
接下來就這幾種前端經常使用的存儲方式進行介紹。前端
cookie就是存儲在客戶端的一小段文本,大小不能超過4kb,在請求接口的時候,cookie會被請求攜帶着,進而被服務器所讀取使用。
打開瀏覽器控制檯,F12>>Application>>Cookies,隨便選擇一個域,咱們能夠看到裏面有不少cookie,以下所示:html5
cookie的名稱
cookie的值,大小最大4Kb
cookie存儲的域名
cookie存儲的路徑
cookie的大小
這兩個屬性涉及到 cookie 的存活時間
Expires 屬性指定一個具體的到期時間,到了這個指定的時間以後,瀏覽器就再也不保留這個 cookie ,它的值是 UTC 格式,可使用 Date.prototype.toUTCString() 格式進行轉換。web
Max-Age 屬性制定了從如今開始 cookie 存在的秒數,好比 60 * 60 (即一小時)。過了這個時間之後,瀏覽器就再也不保留這個 Cookie。sql
Max-Age的優先級比Expires高,若是二者都不設置,則這個cookie會在瀏覽器關閉的時候失效。
若是設置了該屬性,意思就是這個cookie不能被JavaScript取到,也就防止了cookie被腳本讀取,而後當發起請求的時候,該cookie纔會被帶上。
指定瀏覽器只有在加密協議 HTTPS 下才能發送cookie,不須要設置,當協議是https時,會自動開啓。
/** * 設置cookie * @param {*} key 名稱 * @param {*} val 值 * @param {*} time 失效時間 */ export const setCookie = (key, val, time) => { var date = new Date(); var expiresDays = time; //將時間轉換爲cookie設置時間的格式 date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000); document.cookie = key + "=" + val + ";expires=" + date.toDateString(); }
/** * 獲取cookie * @param {*} key 名稱 */ export const getCookie = (key) => { var getCookie = document.cookie.replace(/[ ]/g, ""); var arrCookie = getCookie.split(";") var tips; for (var i = 0; i < arrCookie.length; i++) { var arr = arrCookie[i].split("="); if (key == arr[0]) { tips = arr[1]; break; } } return tips; }
刪除cookie的話,能夠直接調用設置cookie的方法,將失效時間置爲-1,以下:數據庫
setCookie(key,'',-1)
localStorage/sessionStorage是在html5中新加入的技術,二者除了數據的時效性不同以外,其餘都同樣。大小通常爲5MB,存儲的時候,僅僅在客戶端存儲,不會隨着請求的調用而傳遞到服務器。api
localStorage不手動刪除則永久有效,sessionStorage僅在當前會話有效
下面F12>>Application>>Cookies看一個存儲示例:數組
能夠看到,其只有兩個屬性,也就是key(名稱)、value(值)瀏覽器
localStorage和sessionStorage都具備相同的操做方法,例如setItem、getItem和removeItem等,爲了使用方便,咱們對其進行二次封裝,示例以下:服務器
/** * 存儲Storage */ export const setStore = (params = {}) => { let { name,//名稱 content,//內容 type,//類型 } = params; let obj = { dataType: typeof (content), content: content, type: type, datetime: new Date().getTime() } if (type) window.sessionStorage.setItem(name, JSON.stringify(obj)); else window.localStorage.setItem(name, JSON.stringify(obj)); }
/** * 判斷是否爲空 */ function validatenull (val) { if (typeof val === 'boolean') { return false } if (typeof val === 'number') { return false } if (val instanceof Array) { if (val.length == 0) return true } else if (val instanceof Object) { if (JSON.stringify(val) === '{}') return true } else { if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true return false } return false } /** * 獲取Storage */ export const getStore = (params = {}) => { let { name,//名稱 debug//是否須要轉換類型 } = params; let obj = {}, content; obj = window.sessionStorage.getItem(name); if (validatenull(obj)) obj = window.localStorage.getItem(name); if (validatenull(obj)) return; try { obj = JSON.parse(obj); } catch{ return obj; } if (debug) { return obj; } if (obj.dataType == 'string') { content = obj.content; } else if (obj.dataType == 'number') { content = Number(obj.content); } else if (obj.dataType == 'boolean') { content = eval(obj.content); } else if (obj.dataType == 'object') { content = obj.content; } return content; }
/** * 刪除localStorage */ export const removeStore = (params = {}) => { let { name, type } = params; if (type) { window.sessionStorage.removeItem(name); } else { window.localStorage.removeItem(name); } }
/** * 獲取所有Storage */ export const getAllStore = (params = {}) => { let list = []; let { type } = params; if (type) { for (let i = 0; i <= window.sessionStorage.length; i++) { list.push({ name: window.sessionStorage.key(i), content: getStore({ name: window.sessionStorage.key(i), type: 'session' }) }) } } else { for (let i = 0; i <= window.localStorage.length; i++) { list.push({ name: window.localStorage.key(i), content: getStore({ name: window.localStorage.key(i), }) }) } } return list; }
/** * 清空所有Storage */ export const clearStore = (params = {}) => { let { type } = params; if (type) { window.sessionStorage.clear(); } else { window.localStorage.clear() } }
我的推薦在項目中使用storage存儲,cookie存儲數據過多,會形成性能問題。固然,你們能夠根據實際狀況進行選擇,二次封裝方法已雙手奉上。
對於簡單的數據存儲,storage和cookie就已經夠用了,可是若是須要存儲比較複雜的關係型數據,再使用storage和cookie,就有點力不從心了。這個時候可使用webSQL或者indexDB進行存儲。
Web SQL數據庫API是一個獨立的規範,在瀏覽器層面提供了本地對結構化數據的存儲,已經被不少現代瀏覽器支持了。
從上面的圖中能夠看出,webSQL兼容性並非太好,所以使用時,咱們須要先判讀那瀏覽器是否支持。
if (window.openDatabase) { // 操做 web SQL } else { alert('當前瀏覽器不支持 webSQL !!!'); }
webSQL操做類封裝代碼量較大,此處就再也不展現,須要的小夥伴能夠關注我公衆號回覆【webSQL操做類】獲取。下面給個簡單的例子:
var myDB = { name: 'formData', version: 1, db: null, }; myDB.db = openDatabase(myDB.name, myDB.version, 'test', 100 * 1024 * 1024); myDB.db.transaction(function(tx) { tx.executeSql('', [], function(tx, result) { if(result.rows.length!=0){ //result.rows.item(i) } }, function(tx, error) { console.log(error); }); })
經常使用的SQL語句:
//新建表 'CREATE TABLE IF NOT EXISTS 表名 (列名稱1 PRIMARY KEY,列名稱2 UNIQUE ,列名稱3)' //刪除表 'DROP TABLE 表名' //清空表 'DELETE FROM 表名' //刪除條目 'DELETE FROM 表名 WHERE 列名稱1 = ? and 列名稱2 = ?' //新增一條 'INSERT INTO 表名 VALUES (?,?,?,?,?,?,?)' //爲全部列添加值 'INSERT INTO 表名 (列名稱2,列名稱4,列名稱6) VALUES (?,?,?)' //爲指定列添加值 //批量增長 insert into persons (id_p, lastname , firstName, city ) values (200,'haha' , 'deng' , 'shenzhen'), (201,'haha2' , 'deng' , 'GD'), (202,'haha3' , 'deng' , 'Beijing') //更新一條 'UPDATE 表名 SET 列名稱1 = ? where 列名稱2 = ? AND 列名稱3 = ?' 'UPDATE 表名 SET 列名稱1 = ?,列名稱2 = ?,列名稱3 = ? where 列名稱2 = ? AND 列名稱3 = ?' //根據主鍵存在與否,更新或添加一條數據 'replace into 表名 (列名稱1,列名稱2,列名稱3,列名稱4,列名稱5) VALUES (?,?,?,?,?) ' //查找(更多查詢請根據本身的須要自由組合) 'select * from 表名 where 列名稱1 = ? and 列名稱1 >= ?' //常規查找 'select * from 表名 where 列名稱1 = ? or 列名稱1 >= ?' //常規查找 'select * from 表名 ORDER BY ?' //指定排序項 'select * from 表名 ORDER BY ? LIMIT 2;'//只查找符合條件的2條 WHERE 列名稱 IS NOT NULL //非空 WHERE 列名稱 LIKE "111%" //111開頭的 WHERE 列名稱 LIKE "%111" //111結尾的 WHERE 列名稱 LIKE "%111%" //包含111的 WHERE 列名稱 NOT LIKE "%111%" //不包含111的 '_a_' //三位且中間字母是a的 '_a' //兩位且結尾字母是a的 'a_' //兩位且開頭字母是a的 WHERE 列名稱 GLOB > 111 //大於111 WHERE 列名稱 GLOB >= 111 //大於等於111 WHERE 列名稱 GLOB != 111 //不等於111 WHERE 列名稱 GLOB '111*' //111開頭的 WHERE 列名稱 IN ( 25, 27 ) //值爲25或27的 WHERE 列名稱 NOT IN ( 25, 27 ) //值不爲25或27的 WHERE 列名稱 BETWEEN 25 AND 27 //值在25到27之間的 WHERE 列名稱 IN ( '25', '27' ) //注意:拼接sql時不要忘記引號 //索引 'CREATE INDEX IF NOT EXISTS 索引名 on 表名 (列名稱1, 列名稱2) ' 'DROP INDEX 索引名'
IndexedDB標準是HTML5官方承認的本地數據庫解決方案。其目的不是取代服務器端數據庫,它在一些特定場景下頗有用,好比離線應用。IndexedDB是一種輕量級NOSQL數據庫,是由瀏覽器自帶。相比Web Sql更加高效,包括索引、事務處理和查詢功能。
從上圖能夠看出indexDB的兼容性仍是不錯的。
首先咱們須要建立或者打開一個數據庫對象,可使用window.indexedDB.open()方法,示例以下:
var openRequest =window.indexedDB.open(name, version); var db; openRequest.onupgradeneeded = function(e) { console.log("Upgrading...");} openRequest.onsuccess = function(e) { console.log("Success!"); db = e.target.result; } openRequest.onerror = function(e) { console.log("Error"); console.dir(e); }
第一次打開數據庫時,會先觸發upgradeneeded事件,而後觸發success事件
open方法返回的是一個對象(IDBOpenDBRequest),回調函數定義在這個對象上面
回調函數接受一個事件對象event做爲參數,它的target.result屬性就指向打開的IndexedDB數據庫
數據庫對象有了,咱們還須要建立一個存放數據的「對象倉庫」,示例以下:
db.createObjectStore("test", { keyPath: "email" }); db.createObjectStore("test2", { autoIncrement: true });
keyPath表示的是存儲數據的鍵名,autoIncrement表示是否使用自動遞增的整數做爲鍵名。通常來講,兩個屬性有一個就能夠了。
transaction方法用於建立一個數據庫事務。向數據庫添加數據以前,必須先建立數據庫務。
transaction方法返回一個事務對象,該對象的objectStore方法用於獲取指定的對象倉庫。
var transaction = db.transaction(["firstOS"],"readwrite"); var store = transaction.objectStore("firstOS");
transaction方法接受兩個參數:
第一個參數是一個數組,裏面是所涉及的對象倉庫,一般是隻有一個;
第二個參數是一個表示操做類型的字符串。readonly(只讀)和readwrite(讀寫);
transaction方法有三個事件,能夠用來定義回調函數。
abort: 事務中斷; complete: 事務完成; error: 事務出錯。
transaction.oncomplete = function(event) { // some code };
transaction對象提供了一些api,供咱們操做數據。
獲取對象倉庫之後,就能夠用add方法往裏面添加數據了,示例以下:
var transaction = db.transaction(["firstOS"],"readwrite"); var store = transaction.objectStore(「firstOS」); var data = {name: 'monkey'}; var request = store.add(data,1); request.onerror = function(e) { console.log("Error",[e.target.error.name](http://e.target.error.name)); } request.onsuccess = function(e) { console.log("數據添加成功!"); }
add方法的第一個參數是所要添加的數據,第二個參數是這條數據對應的鍵名(key),上面代碼將對象o的鍵名設爲1。若是在建立數據倉庫時,對鍵名作了設置,這裏也能夠不指定鍵名。
var data = { name: 'monkeysoft' }; var request = store.put(data);
var request = store.get(key);
var request = store.delete(key);
var request = store.clear();
var request = store.openCursor();
indexDB操做類封裝代碼量較大,此處就再也不展現,須要的小夥伴能夠關注我公衆號回覆【indexDB操做類】獲取
以上就是我對前端本地存儲的一些理解和整理,若有錯,歡迎各位大佬指正,省得誤人子弟~嘿嘿。
參考:
一、indexDB講解與封裝 https://www.jianshu.com/p/136...