【JavaScript】離線應用與客戶端存儲

来源:https://www.cnblogs.com/lovecsharp094/archive/2018/02/12/8440979.html
-Advertisement-
Play Games

一、前言 這章非常重要,由於之後需要負責平臺手機APP的日後維護,如何讓用戶在離線狀態下正常使用,以及聯網後的數據合併變得非常重要。 二、內容 離線檢測 數據存儲 ...


一、前言

       這章非常重要,由於之後需要負責平臺手機APP的日後維護,如何讓用戶在離線狀態下正常使用,以及聯網後的數據合併變得非常重要。

 

二、內容

       離線檢測

navigator.online —— 屬性為true時表示設備能上網
online() —— 當網路從離線轉線上觸發
offline() —— 當網路從線上轉離線觸發

navigator.online取得初始狀態,然後通過上述兩個事件確定網路連接狀態是否變化

      數據存儲

//Cookie
數量:每個域的cookie總數是有限的,一般每個域最多30~50個cookie
長度:整個cookie的長度限制在4095B以內

構成:

1.名稱 URL編碼
2.值 URL編碼
3.域
4.路徑 —— 指定域下的某個路徑才能訪問
5.失效時間
6.安全標誌 —— 指定後cookie只有在使用SSL連接的時候才發送伺服器

代碼:

var CookieUtil = {

// 獲取Cookie
get:function(name){
var cookieName = encodeURIComponent(name)+"=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;

if(cookieStart > -1){
var cookieEnd = document.cookie.indexOf(";",cookieStart);
if(cookieEnd == -1){
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(
cookieStart + cookieName.length, cookieEnd));
}
return cookieValue;
},

//設置Cookie
set:function(name, value, expires, path, domain, secure){
var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
if(expires instanceof Date){
cookieText += "; expires=" + expores.toGMTString();
}
if(path){
cookieText += "; path=" + path;
}
if(domain){
cookieText += "; domain=" + domain;
}
if(secure){
cookieText += "; secure";
}
document.cookie = cookieText;
},

//刪除Cookie
unset:function(name,path,domain,secure){
this.set{name, "", new Date(0), path, domain, secure};
}

}

//子Cookie
使用cookie值來存儲多個名稱值對
name=name1=value1&name2=value2&name3=value3

總結:
1.cookie太大容易影響性能
2.不能在cookie中存儲重要和敏感的數據

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


//Web存儲機制 —— Web Storage
1.提供一種在cookie之外存儲會話數據的途徑
2.提供一種存儲大量可以跨會話存在的數據的機制


Storage類型,有以下方法:
clear() —— 刪除所有值
getItem(name) —— 根據名稱獲得值
key(index) —— 獲得index處的值的名字
removeItem(name) —— 刪除由name指定的名值對
setItem(name,valie) —— 為指定的name設置一個對應值

sessionStorage對象
該對象存儲特定與某個會話的數據,該數據只保存到瀏覽器關閉,它是Storage的一個實例

//使用方法存儲數據
sessionStorage.setItem("name", "Nicholas");
//使用屬性存儲數據
sessionStorage.book = "Nicholas";
//遍歷
for(var key in sessionStorage){
var value = sessionStorage.getItem(key);
}

用途:sessionStorage對象主要用於僅針對會話的小段數據的存儲

globalStorage對象
用途:globalStorage對象主要用於跨越會話存儲數據,但有特定的訪問限制,需要指定域
globalStorage["wrox.com"]對象是Storage的一個實例
使用時一定要指定一個功能變數名稱!!!

//保存數據
globalStorage["wrox.com"].name = "Nicholas";

//獲取數據
var name = globalStorage["wrox.com"].name;

localStorage對象
它是Storage的一個實例不能給localStorage指定任何訪問規則;規則事先就設定好了
要訪問一個localStorage對象,頁面必須來自同一功能變數名稱(子功能變數名稱無效),使用同一種協議,在同一埠上
相當於globalStorage[location.host]

storage事件
在Storage對象進行任何修改,都會在文檔上觸發storage事件,有以下屬性:
domain:發送變化的存儲空間的功能變數名稱
key:設置或刪除的鍵名
newValue:如果是設置值,則是新值;如果是刪除鍵,則是null
oldValue:鍵被更改之前的值

總結:
1.因瀏覽器不同而對存儲空間大小有限制

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//IndexedDB —— 在瀏覽器保存結構化數據的一種資料庫
IndexedDB設計的操作完全是非同步進行的
差不多每一次IndexedDB操作,都需要註冊onerror或onsuccess事件
var indexedDB = window.indexedDB || windows.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;


1.資料庫
var request, database;
request = indexedDB.open("admin"); //傳入資料庫名稱
request.onerror = function(event){
alert("open fail" + event.target.errorCode); //出現錯誤
};
request.onsucess = function(event){
database = event.target.result; //得到資料庫實例
};

預設情況下,IndexedDB資料庫是沒有版本號的,最好一開始就指定
if(database.version != "1.0"){
request = database.setVersion("1.0");
request.onerror = function(event){};
request.onsuccess = function(event){};
}else{}


2.對象存儲空間
資料庫建立連接後,下一步是使用對象存儲空間。
如果資料庫的版本與傳入的版本不匹配,那麼可能需要創建一個新的對象存儲對象。

假設一條記錄的對象如下所示:
var user = {
username:"007",
firstName:"James",
lastName:"Bond",
password:"foo"
};


var store = db.createObjectStore("users",{keyPath:"username"}); //指定空間名稱及keyPath作為鍵
//使用add()或put()添加數據 —— store.add() / store.put()
//其中add()方法重寫會返回錯誤,put()重寫原有對象沒問題

3.事務
創建完對象存儲空間之後,接下來所有操作都是通過事務來完成的
調用transaction()創建事務
var transaction = db.transaction();
//或

var transaction = db.transaction("users"); //訪問一個對象
//或
var transaction = db.transaction("users","anotherStore"); //訪問多個對象

上述方法都是以只讀方式訪問數據,如果修改訪問方式:
var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
var transaction = db.transaction("users",IDBTransaction.READ_WRITE);
其中:
IDBTransaction.READ_ONLY —— 只讀
IDBTransaction.READ_WRITE —— 讀寫
IDBTransaction.VERSION_CHANGE —— 改變

使用objectStore()並傳入存儲空間的名稱就可以訪問特定的存儲空間:
var request = db.transaction("users").objectStore("users").get("007");
request.onerror = function(event){
//do something
}
request.onsuccess = function(event){
var result = event.target.result;
alert(result.firstName);
}
事件本身也有事件處理程式:
transaction.onerror = function(event){//整個事務都被取消};
transaction.oncomplete = function(event){
//整個事務都成功完成,但訪問不到event中的任何數據,
//必須在相應請求的onsuccess事件中才能訪問
}; 


4.使用游標查詢
檢索多個對象時,需要在事務內創建游標 openCursor()
var store = db.transaction("users").objectStore("users"),
request = store.openCursor();
request.onerror = function(event){};
request.onsuccess = function(event){
var cursor = event.target.result; //返回一個IDBCursor實例
if(cursor){ //必須要檢查
//do something
}
};
IDBCursor屬性包含:
direction —— 游標移動方向
IDBCursor.NEXT(0) 下一項
IDBCursor.NEXT_NO_DUPLICATE(1) 下一個不重覆項
IDBCursor.PREV(2) 前一項
IDBCursor.PREV_NO_DUPLICATE 一個不重覆項
key —— 對象的鍵
value —— 實際的對象,顯示前需要使用JSON.stringify(value)來轉成Json對象
primaryKey —— 游標使用的鍵


游標可以更新個別的記錄 —— cursor.update()

request.onsuccess = function(event){
var cursor = event.target.result,
value,
updateRequest;
if(cursor){
if(cursor.key == "foo"){
value = cursor.value;
value.password = "magic!";

updateRequest = cursor.update(value); //請求保存更新
udpateRequest.onsuccess = function(){//處理成功};
udpateRequest.onerror = function(){//處理成功};
}
}
}
游標也可以調用cursor.delete()刪除相應記錄,
如果當前事務沒有修改對象存儲空間的許可權,update()與delete()會拋出錯誤

預設情況下,每個游標只發起一次請求,要想發起另一次請求,可以調用:
continue(key) —— 移動到結果集中的下一項
advance(count) —— 向前移動count指定的項數

5.鍵範圍
單純通過游標查詢數據的方式太有限,鍵範圍增加了靈活性
var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;

only():
var onlyRange = IDBKeyRange.only("007");

lowerBound():
var lowerRange = IDBKeyRange.lowerBound("007"); //從007開始到最後,包含007
var lowerRange = IDBKeyRange.lowerBound("007",true); //從007開始到最後,不包含007

upperBound():
var upperRange = IDBKeyRange.upperBound("007"); //從007開始往上,包含007
var upperRange = IDBKeyRange.upperBound("007",true); //從007開始往上,不包含007

Bound():
var boundRange = IDBKeyRange.bound("下界鍵","上界鍵",是否跳過下界,是否跳過上界);

例:
var store = db.transaction("users").objectStore("users");
range = IDBKeyRange.bound("007","ace");
request = store.openCursor(range);

request.onsuccess = function(event){
var cursor = event.target.result;
if(cursor){};
}

6.設定游標方向
var IDBCursor= window.IDBCursor || window.webkitIDBCursor;

var store = db.transaction("users").objectStore("users"),
request = store.openCursor(null, IDBCursor.NEXT_NO_DUPLICATE);//null為預設全範圍


7.索引
對於某些數據,可能要為一個對象存儲空間指定多個鍵,即主鍵與索引鍵
首先引用對象存儲空間,然後調用createIndex()

var store = db.transaction("users").objectStore("users"),
index = store.createIndex("username","username",{unique:false}); //其它空間也有可能含username

第一個參數:索引的名稱
第二個參數:索引的屬性的名字
第三個參數:是否在所有記錄中唯一

使用一個已經存在的名為"username"的索引:
var store = db.transaction("users").objectStore("users");
index = store.index("username");
request = index.openCursor();
//如果只返回每條記錄主鍵的游標:
request = index.openKeyCursor();

request.onsuccess = function(event){
//event.result.key中保存索引鍵
//event.result.value保存主鍵
};


//get()方法能夠從索引中取得一個對象
request = index.get("007");
//要根據給定的索引鍵取得主鍵,使用getKey()
request = index.getKey("007");

IDBIndex對象含以下屬性:
name —— 索引的名稱
keyPath —— 傳入createIndex()中的屬性路徑
objectStore —— 索引的對象存儲空間
unique —— 標識索引鍵是否唯一


store.indexNames能訪問到為該空間建立的所有索引
store.deleteIndex("name")則可以根據索引的名稱刪除索引


8.併發問題
如果瀏覽器的兩個不同的標簽頁打開了同一頁面,那麼一個頁面試圖更新另一個頁面尚未
準備就緒的資料庫問題就有可能發生。因此,只有當瀏覽器中僅有一個標簽頁使用資料庫情況下,調用setVersion()才能完成操作

正確的方式:
剛打開資料庫時,要記著指定onversionchange事件處理程式。當同一個來源的另一個標簽頁調用setVersion()時,就會執行這個回調:
var request, database;
request = indexedDB.open("admin");
request.onsuccess = function(event){
database = event.target.result;
database.onversionchange = function(){
database.close()
};
}


在你想要更新資料庫的版本但另一個標簽頁已經打開資料庫的情況下,要觸發onblocked事件:
var request= database.setVersion("2.0");
request.onblocked = function(){
alert("Please close all other tabs");
};
request.onsuccess = function(){
//do something
};

總結:
1.不能跨域共用信息
2.大約5MB或50MB的空間限制

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 結論:使用合法屬性名,使用 . 和 [] 訪問都可以; 如果屬性名是數字,則必須用“”包圍,並且用 [] 方括弧訪問。 ...
  • 編寫Javascript的開發者都知道,JS雖然沒有類(ES6添加了class語法),但是可以模擬出OOP語言的類和麵向對象的概念,比如我們都知道的一句話,Javascript中處處是對象,而面向對象語言的特性是繼承,封裝,多態,抽象,而本文討論的是Javascript的繼承,Javascript的 ...
  • 瀏覽器引擎預設:webkit內核 一、輸入地址 當我們開始在瀏覽器中輸入網址的時候,現代瀏覽器就可以智能的匹配完整 url了,它會從歷史記錄,書簽等地方,找到已經輸入的字元串可能對應的 url,然後給出智能提示,讓你可以補全url地址。 如果輸入的地址和候選項很匹配,在敲下回車之前,chromium ...
  • 1.需要用到的方法: Math.random:取大於等於0到小於1之間的隨機數; Math.floor:向下取整; Math.ceil:向上取整; 2.看了一個面試題,要求有個函數fn,參數為n,需要返回[2,32]之間的n個整數。第一次寫的時候如下: 然後發現2到32包含2和32的時候是有31位數 ...
  • 在移動端 H5 頁面開發中,我使用了 fixed 固定某個元素在屏幕的最下方, 這時點擊輸入框,接著非常非常自然地出現了元素被系統鍵盤頂起來的情況,如下圖。 解決方案: 首先,給頁面最外層包裹一層 div(相對定位) ,然後頁面渲染完成時給 div 的高度等於 body(document.body. ...
  • 三欄佈局左右固定,中間自適應是網頁中常用到的,實現這種佈局的方式有很多種,這裡我主要寫五種。他們分別是浮動、定位、表格、flexBox、網格。 在這裡也感謝一些老師在網上發的免費教程,使我們學習起來更方便!!! 先讓大家看一下頁面效果圖: 代碼我也給寫了註釋了,這個是很基礎的一些知識點,下麵就是他們 ...
  • 一、前言 上一章學習完了Js的一些基本內容,本章開始學習JQuery語法。JQuery的基礎語法是: 那麼重要的兩個元素,一個是選擇器,另一個是行為!本章開始學習JQuery的選擇器。 二、內容 ...
  • 在前端的開發過程中,免不了進行各種調試和測試。 在不同的平臺,不同的環境下的調試方法也不盡相同,這個系列文章將探索常見的一些前端調試場景,較為系統地整理出一些調試方法。 主要包含在 PC上的 IE、FireFox、Chrome、Safari、Edge瀏覽器開發工具調試,遠程真機 安卓微信頁面、安卓常 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...