<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 離線應用與客戶端存儲 Web應用允許使用瀏覽器提供的API實現將數據存儲到用戶的電腦上。 **1、cookie** cookie是指Web瀏覽器存儲的少量數據,每個Cookie的大小一般不能超過4KB。 Cookie保存以下幾方面的信息。 - Cookie的名字 - Cookie的值 - 到期時間 - 所屬域名(默認是當前域名) - 生效的路徑(默認是當前網址) 我們可以通過特殊的格式的字符串形式來讀寫Document對象的cookie屬性。 ``` document.cookie //讀取當前頁面的所有cookie ``` 我們可以通過檢查navigator.cookieEnabled屬性來檢測當前cookie是否啟用。若值為true,表示cookie是啟用的。 **1.1 cookie屬性:有效期和作用域** cookie默認的有效期很短暫,它只能持續在Web瀏覽器的會話期間,一旦用戶關閉瀏覽器,cookie保存的數據就會丟失。 注意:cookie的有效期和sessionStorage的有效期是有區別的:cookie的作用域并不是局限在瀏覽器的單個窗口中,它的有效期和整個瀏覽器進程而不是單個瀏覽器窗口的有效期一致。 cookie的作用域是通過文檔源和文檔路徑來確定的。 **1.2 保存cookie** document.cookie屬性是可寫的,可以通過它為當前網站添加Cookie。 ``` document.cookie = 'user=TG'; ``` Cookie的值必須寫成key=value的形式。注意,等號兩邊不能有空格。另外,寫入Cookie的時候,必須對分號、逗號和空格進行轉義(它們都不允許作為Cookie的值),這可以用encodeURIComponent方法進行編碼,讀取時再采用decodeURIComponent方法解碼。 但是,document.cookie一次只能寫入一個Cookie,而且寫入并不是覆蓋,而是添加。 ``` document.cookie = 'test1=hello'; document.cookie = 'test2=world'; document.cookie // test1=hello; test2=world ``` 如果要延長cookie的有效期,就需要設置mav-age屬性來指定cookie的有效期(單位是秒) ``` document.cookie = 'user=TG;max-age=60*60*24'; //將有效期設置為一天 ``` **1.3 讀取cookie** 使用JavaScript表達式來讀取cookie屬性時,其返回的值是一個字符串,該字符串都是由一系列名/值對組成,不同名/值對之間通過“分號和空格”分開,其內容包含了所有作用在當前文檔的cookie。 一般情況下,我們會采用split()方法將cookie值中的名/值對都分離出來。當然,如果之前進行了一系列的編碼,就需要先解碼再分離。 ``` function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for(var i=0; i<ca.length; i++) { var c = ca[i].trim(); if (c.indexOf(name)==0) { return c.substring(name.length,c.length); } } return ""; } ``` **1.4 其他屬性** 除了Cookie本身的內容,還有一些可選的屬性也是可以寫入的,它們都必須以分號開頭。 ``` Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure] ``` 上面的Set-Cookie字段,用分號分隔多個屬性: **(1)value屬性** value屬性是必需的,它是一個鍵值對,用于指定Cookie的值。 **(2)expires屬性** expires屬性用于指定Cookie過期時間。它的格式采用Date.toUTCString()的格式。 ``` expires=Thu, 01 Jan 1970 00:00:00 GMT ``` 如果不設置該屬性,或者設為null,Cookie只在當前會話(session)有效,瀏覽器窗口一旦關閉,當前Session結束,該Cookie就會被刪除。 瀏覽器根據本地時間,決定Cookie是否過期,由于本地時間是不精確的,所以沒有辦法保證Cookie一定會在服務器指定的時間過期。 **(3)domain屬性** domain屬性指定Cookie所在的域名,比如example.com或.example.com(這種寫法將對所有子域名生效)、subdomain.example.com。 如果未指定,默認為設定該Cookie的域名。所指定的域名必須是當前發送Cookie的域名的一部分,比如當前訪問的域名是example.com,就不能將其設為google.com。只有訪問的域名匹配domain屬性,Cookie才會發送到服務器。 **(4)path屬性** path屬性用來指定路徑,必須是絕對路徑(比如/、/mydir),如果未指定,默認為請求該Cookie的網頁路徑。 只有path屬性匹配向服務器發送的路徑,Cookie才會發送。這里的匹配不是絕對匹配,而是從根路徑開始,只要path屬性匹配發送路徑的一部分,就可以發送。比如,path屬性等于/blog,則發送路徑是/blog或者/blogroll,Cookie都會發送。path屬性生效的前提是domain屬性匹配。 **(5)secure** secure屬性用來指定Cookie只能在加密協議HTTPS下發送到服務器。 該屬性只是一個開關,不需要指定值。如果通信是HTTPS協議,該開關自動打開。 **(6)max-age** max-age屬性用來指定Cookie有效期,比如60 * 60 * 24 * 365(即一年31536e3秒)。 **2.5 cookie的限制** 瀏覽器對Cookie數量的限制,規定不一樣。目前,Firefox是每個域名最多設置50個Cookie,而Safari和Chrome沒有域名數量的限制。 所有Cookie的累加長度限制為4KB。超過這個長度的Cookie,將被忽略,不會被設置。 由于Cookie可能存在數量限制,有時為了規避限制,可以將cookie設置成下面的形式。 ``` name=a=b&c=d&e=f&g=h ``` 上面代碼實際上是設置了一個Cookie,但是這個Cookie內部使用&符號,設置了多部分的內容。因此,讀取這個Cookie的時候,就要自行解析,得到多個鍵值對。這樣就規避了cookie的數量限制。 **2、localStorage和sessionStorage** `localStorage`和`sessionStorage`這兩個屬性都代表同一個Storage對象(一個持久化關聯數組,數組使用字符串來索引,存儲的值都是字符串形式的)。 **2.1 存儲有效期和作用域** `localStorage`和`sessionStorage`的區別在于存儲的有效期和作用域的不同。 **2.1.1 localStorage** 通過`localStorage`存儲的數據是永久性的,除非Web應用刻意刪除存儲的數據或用戶通過設置瀏覽器設置來刪除,否則數據將一直保留在用戶的電腦里,永不過期。 `localStorage`的作用域是限定在文檔源(document origin)級別。 同源的文檔間共享同樣的`localStorage`數據。 **2.1.2 sessionStorage** `sessionStorage`的作用域同樣是限定在文檔源中,不過它被限定在窗口中。也就是說,如果同源的文檔在不同的瀏覽器標簽頁中,那它們互相之間擁有的是各自的`sessionStorage`數據,無法共享。 注意:基于窗口作用域的`sessionStorage`指的窗口只是頂級窗口。如果一個瀏覽器標簽頁包含多個`<iframe>`元素,它們包含的文檔是同源的,兩者之間的sessionStorage是可共享的。 **2.2 存儲API** 我們可以將`localStorage`和`sessionStorage`當做普通的JavaScript對象:通過設置屬性來存儲字符串值,查詢該屬性來讀取該值。 ``` localStorage.user = 'TG'; ``` 當然,這兩個對象也提供了對應的存儲(`setItem()`)和讀取(`getItem()`)的方法。 ``` localStorage.setItem('user','TG'); //存儲一個以“user”的名字存儲的數值。 localStorage.getItem('user'); //讀取 ``` 同樣,`sessionStorage`也有這兩個方法。 ``` sessionStorage.setItem('user','TG'); sessiontStorage.getItem('user'); ``` 還可以使用`removeItem()`和`clear()`方法來刪除。 ``` localStorage.removeItem('user'); //刪除名為“user”的數據。 localStorage.clear(); //刪除所有存儲的數據 sessionStorage.removeItem('user'); sessionStorage.clear(); ``` 遍歷存儲數據。 ``` for(var i=0; i < localStorage.length; i++){ var name = localStorage.key(i); //獲取第i對的名字 console.log(localStorage.getItem(name); //獲取該對的值 } ``` 其中的`key`方法,根據位置(從0開始)獲得鍵值。 ``` localStorage.key(1); ``` **2.3 storage事件** 當儲存的數據發生變化時,會觸發storage事件。我們可以指定這個事件的回調函數。 ``` window.addEventListener("storage",onStorageChange); ``` 回調函數接受一個event對象作為參數。這個event對象的key屬性,保存發生變化的鍵名。 ``` function onStorageChange(e) { console.log(e.key); } ``` 除了key屬性,event對象的屬性還有三個: - oldValue:更新前的值。如果該鍵為新增加,則這個屬性為null。 - newValue:更新后的值。如果該鍵被刪除,則這個屬性為null。 - url:原始觸發storage事件的那個網頁的網址。 值得特別注意的是,該事件不在導致數據變化的當前頁面觸發。如果瀏覽器同時打開一個域名下面的多個頁面,當其中的一個頁面改變sessionStorage或localStorage的數據時,其他所有頁面的storage事件會被觸發,而原始頁面并不觸發storage事件。可以通過這種機制,實現多個窗口之間的通信。所有瀏覽器之中,只有IE瀏覽器除外,它會在所有頁面觸發storage事件。 **3、客戶端數據庫(IndexedDB)** IndexedDB(對象數據庫)可以說是瀏覽器端數據庫,可以被網頁腳本程序創建和操作。它允許儲存大量數據,提供查找接口,還能建立索引。 在IndexedDB API中,一個數據庫就是一個命名對象倉庫(object store)的集合,對象存儲區存儲的是對象。 IndexedDB特點: - 鍵值對存儲:在對象倉庫中,數據以“鍵值對”的形式保存,每一個數據都有對應的鍵名,鍵名是獨一無二的,不能有重復,否則會拋出一個錯誤。 - 同域限制:IndexedDB數據庫的作用域是限制在包含它們的文檔源中,每一個數據庫對應創建該數據庫的域名,兩個同源的Web頁面互相之間可以訪問對方的數據,但非同源的頁面就不行。 - 支持事務:IndexedDB支持事務,這就是說對數據庫的查詢和更新都是包含在一個事務(transaction)中,以此來確保這些操作要么是一起成功,要么是一起失敗,并且永遠不會讓數據庫出現更新到一半的情況。 - 異步:IndexedDB的操作不會阻塞瀏覽器的UI主線程。 - 儲存空間大:IE的儲存上限是250MB,Chrome和Opera是剩余空間的某個百分比,Firefox則沒有上限。 **3.1 檢測瀏覽器是否支持IndexedDB API** ``` if('indexedDB' in window){ //支持 }else{ //不支持 } ``` **3.2 訪問數據庫** 要異步訪問數據庫,就要調用 window 對象 indexedDB 屬性的 open() 方法 ``` var request = indexedDB.open(name[,version]) ``` indexedDB.open方法可傳輸人兩個參數:name是數據庫名稱,必填;version是數據庫版本,是一個大于0的正整數(0將報錯)。 open方法返回一個 IDBRequest 對象 (IDBOpenDBRequest), 注意:如果數據庫存在,將打開數據庫,否則,則會新建該數據庫。如果省略第二個參數,則會自動創建版本為1的該數據庫。 當打開數據時,有可能觸發4種事件: success:打開成功。 error:打開失敗。 upgradeneeded:第一次打開該數據庫,或者數據庫版本發生變化。 blocked:上一次的數據庫連接還未關閉。 第一次打開數據庫時,會先觸發upgradeneeded事件,然后觸發success事件。 ``` request.onupgradeneeded = function(e){} request.onsuccess = function(e){ db = e.target.result; } ``` 回調函數接受一個事件對象event作為參數,它的target.result屬性就指向打開的IndexedDB數據庫。 **3.3 IndexedDB實例對象的方法** **3.3.1 createObjectStore()方法** createObjectStore()方法用于創建存放數據的“對象倉庫”(object store)。 ``` db.createObjectStore(name[,options]); ``` 參數說明: 參數name是對象倉庫的名字;options是可選參數,用來設置對象倉庫的屬性,可配置兩個屬性:keyPath和autoIncrement,分別表示每條記錄的鍵名和是否使用自動遞增的整數作為鍵名,默認為false。 ``` db.createObjectStore('db1', {keyPath: 'user'}); db.createObjectStore('db2', {autoIncrement: true}); ``` 由于對象倉庫的名字具有唯一性(當創建已存在的數據庫時,會報錯),所以在創建對象倉庫時,我們有必要檢測對象倉庫是否已存在: db.objectStoreNames.contains(name) objectStoreNames屬性返回一個DOMStringList對象,里面包含了當前數據庫所有“對象倉庫”的名稱。可以使用DOMStringList對象的contains方法,檢查數據庫是否包含某個“對象倉庫”。 **3.3.2 transaction方法** 創建了數據庫,當然要使用它,不過數據庫的更新、讀取和刪除是建立在事務的基礎上的,所以我們首先要創建一個事務: ``` var t = db.transaction(array,type) ``` transcation()方法接受兩個參數:參數array是一個數組,包含了所要使用的對象倉庫,通常是一個;參數type是一個表示操作類型的字符串,目前只有兩種類型:readonly(只讀)和readwrite(讀寫)。 ``` t = db.transaction(['db1','readwrite'); ``` transaction()方法返回一個事務對象,該對象的objectStore()方法用于獲取指定的對象倉庫: ``` var store = t.objectStore('db1'); ``` 事務對象有三個監聽事件: abort:事務中斷。 complete:事務完成。 error:事務出錯。 假如事務完成時: ``` t.oncomplete =function(e){} ``` **3.3.3 數據操作** 下面的方法都是在事件對象上。 **(1)add()方法** add()方法用來添加數據 ``` var add = store.add(data,key) ``` 參數說明:參數data是所要添加的數據;參數key是這條數據對應的鍵名(key)。 add()方法是異步的,有success和error事件: ``` add.onsuccess = funciton(e){} add.onerror = function(e){} ``` **(2)get()方法** get()方法用來讀取數據,它的參數是鍵名 ``` store.get(key) ``` get方法也是異步的,也有success和error事件。 **(3)put()方法** put()方法用來更新數據,與add()方法類似: ``` var update = store.put(data,key) ``` **(4)delete()方法** delete()方法用來刪除數據,它的參數是鍵名: ``` var delete = store.delete(key) ``` delete方法也是異步的,也有success和error事件。 **(5)openCursor()方法** openCursor()方法用來遍歷數據: ``` var cursor = store.openCursor() ``` openCursor方法也是異步的,也有success和error事件。 ``` cursor.onsuccess = function(e){ var res = e.target.result; console.log('key',res.key); console.log('data',res.value); res.continue() } ``` e.target.result屬性指向當前數據對象。當前數據對象的key和value分別返回鍵名和鍵值(即實際存入的數據)。continue方法將光標移到下一個數據對象,如果當前數據對象已經是最后一個數據了,則光標指向null。 openCursor方法還可以接受第二個參數,表示遍歷方向,默認值為next,其他可能的值為prev、nextunique和prevunique。后兩個值表示如果遇到重復值,會自動跳過。 **3.3.4 createIndex()方法** createIndex()方法用來創建索引: ``` createIndex(index,name,options) ``` createIndex方法接受三個參數,第一個是索引名稱,第二個是建立索引的屬性名,第三個是參數對象,用來設置索引特性。unique表示索引所在的屬性是否有唯一值. **3.3.5 index方法** index()方法用于從對象倉庫返回指定的索引。 ``` var index = store.index(index); var data = index.get(name) ``` 注意:get方法有可能取回多個數據對象,因為name屬性沒有唯一值。 **4、同源策略** 瀏覽器的同源政策規定,兩個網址只要域名相同和端口相同,就可以共享Cookie。 注意:這里不要求協議相同。也就是說,`http://example.com設置的Cookie,可以被https://example.com讀取`。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看