瀏覽器中的不同存儲類型有哪些-創(chuàng)新互聯(lián)

小編給大家分享一下瀏覽器中的不同存儲類型有哪些,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名申請、網(wǎng)絡(luò)空間、營銷軟件、網(wǎng)站建設(shè)、滄州網(wǎng)站維護、網(wǎng)站推廣。

在后端開發(fā)中,存儲是工作的常見部分。應(yīng)用程序數(shù)據(jù)存儲在數(shù)據(jù)庫中,文件存儲在對象存儲中,瞬態(tài)數(shù)據(jù)存儲在高速緩存中……似乎存在無限種存儲任何類型數(shù)據(jù)的可能性。但是,數(shù)據(jù)存儲不僅限于后端,前端(瀏覽器)還具有許多存儲數(shù)據(jù)的選項。我們可以通過利用這種存儲方式來提升我們的應(yīng)用性能,保存用戶的偏好,在多個會話,甚至不同的計算機上保持應(yīng)用狀態(tài)。

在本文中,我們將通過不同的可能性在瀏覽器中存儲數(shù)據(jù)。我們將涵蓋每種方法的三個用例,以掌握其利弊。最后,你將能夠決定什么存儲是最適合你的用例。

讓我們開始吧!

localStorage API

localStorage 是瀏覽器中最受歡迎的存儲選項之一,也是許多開發(fā)人員的選。數(shù)據(jù)跨會話存儲,從不與服務(wù)器共享,并且可用于同一協(xié)議和域下的所有頁面。存儲空間限制為?5MB。

令人驚訝的是,谷歌Chrome團隊并不建議使用這個選項,因為它屏蔽了主線程,而且web workers和service workers無法訪問。他們推出了一個實驗:KV Storage,作為一個更好的版本,但這只是一個試驗,似乎還沒有任何進展。

localStorage API 可作為window.localStorage 使用,并且只能保存UTF-16字符串。在將數(shù)據(jù)保存到localStorage 之前,我們必須確保將其轉(zhuǎn)換為字符串。主要的三個功能是:

  • setItem('key','value')
  • getItem('key')
  • removeItem('key')

它們都是同步的,因此使用起來很簡單,但是它們會阻塞主線程。

值得一提的是,localStorage 有一個稱為sessionStorage 的雙胞胎。的區(qū)別是,存儲在sessionStorage 中的數(shù)據(jù)將僅持續(xù)當(dāng)前會話,但API相同。

這個太簡單了,相信大家都用過。

IndexedDB API

IndexedDB是瀏覽器中的現(xiàn)代存儲解決方案。它可以存儲大量的結(jié)構(gòu)化數(shù)據(jù),甚至文件和Blob。和每一個數(shù)據(jù)庫一樣,IndexedDB對數(shù)據(jù)進行索引,以便高效地運行查詢。使用IndexedDB比較復(fù)雜,我們必須創(chuàng)建一個數(shù)據(jù)庫,表,并使用事務(wù)。

localStorage 相比,IndexedDB需要更多代碼。在例子中,我使用了原生API與Promise包裝器,但我強烈建議使用第三方庫來幫助你。我推薦的是localForage,因為它使用了同樣的localStorage API,但實現(xiàn)方式是逐步增強的,也就是說,如果你的瀏覽器支持IndexedDB,就會使用它;如果不支持,就會退回到localStorage。

讓我們來編寫代碼,前往我們的用戶偏好示例吧!

<input type="checkbox" id="darkTheme" name="darkTheme" onclick='onChange(this);'>
<label for="darkTheme">Dark theme</label><br>
let db;

function toggle(on) {
  if (on) {
    document.documentElement.classList.add('dark'); 
  } else {
    document.documentElement.classList.remove('dark');    
  }
}

async function save(on) {
  const tx = db.transaction('preferences', 'readwrite');
  const store = tx.objectStore('preferences');
  store.put({key: 'darkTheme', value: on});
  return tx.complete;
}

async function load() {
  const tx = db.transaction('preferences', 'readonly');
  const store = tx.objectStore('preferences');
  const data = await store.get('darkTheme');
  return data && data.value;
}

async function onChange(checkbox) {
  const value = checkbox.checked;
  toggle(value);
  await save(value);
}

function openDatabase() {
  return idb.openDB('my-db', 1, {
    upgrade(db) {
      db.createObjectStore('preferences', {keyPath: 'key'});
    },
  });
}

openDatabase()
  .then((_db) => {
    db = _db;
    return load();
  })
  .then((initialValue) => {
    toggle(initialValue);
    document.querySelector('#darkTheme').checked = initialValue;
  });

效果

瀏覽器中的不同存儲類型有哪些

idb 是我們使用的Promise包裝器,而不是使用基于事件的低級API。首先要注意的是,對數(shù)據(jù)庫的每次訪問都是異步的,這意味著我們不會阻塞主線程,與localStorage 相比,這是一個主要優(yōu)勢。

我們需要打開與數(shù)據(jù)庫的連接,以便在整個應(yīng)用程序中都可以使用它進行讀寫。我們給數(shù)據(jù)庫起一個名字my-db,一個模式版本1,以及一個更新函數(shù),以在版本之間應(yīng)用更改,這與數(shù)據(jù)庫遷移非常相似。我們的數(shù)據(jù)庫架構(gòu)很簡單:只有一個object storepreferences。object store 等效于SQL表,要寫入或讀取數(shù)據(jù)庫,必須使用事務(wù),這是使用IndexedDB的乏味部分。看一下演示中新的saveload 功能。

毫無疑問,IndexedDB具有更多的開銷,并且與localStorage 相比,學(xué)習(xí)曲線更陡峭。對于鍵值的情況,使用localStorage 或第三方庫可能更有意義,它們將幫助我們提高效率。

<p id="loading">loading...</p>
<ul id="list">
</ul>
let db;

async function loadPokemons() {
  const res = await fetch('https://pokeapi.co/api/v2/pokemon?limit=10');
  const data = await res.json();
  return data.results;
}

function removeLoading() {
  const elem = document.querySelector('#loading');
  if (elem) {
    elem.parentNode.removeChild(elem); 
  }
}

function appendPokemon(pokemon) {
  const node = document.createElement('li');
  const textnode = document.createTextNode(pokemon.name);
  node.appendChild(textnode);
  document.querySelector('#list').appendChild(node);
}

function clearList() {
  const list = document.querySelector('#list');
  while (list.firstChild) {
    list.removeChild(list.lastChild);
  }
}

function saveToCache(pokemons) {
  const tx = db.transaction('pokemons', 'readwrite');
  const store = tx.objectStore('pokemons');
  pokemons.forEach(pokemon => store.put(pokemon));
  return tx.complete;
}

function loadFromCache() {
  const tx = db.transaction('pokemons', 'readonly');
  const store = tx.objectStore('pokemons');
  return store.getAll();
}

function openDatabase() {
  return idb.openDB('my-db2', 1, {
    upgrade(db) {
      db.createObjectStore('pokemons', {keyPath: 'name'});
    },
  });
}

openDatabase()
  .then((_db) => {
    db = _db;
    return loadFromCache();
  })
  .then((cachedPokemons) => {
    if (cachedPokemons) {
      removeLoading();
      cachedPokemons.forEach(appendPokemon);
      console.log('loaded from cache!');
    }
    return loadPokemons();
  })
  .then((pokemons) => {
    removeLoading();
    saveToCache(pokemons);
    clearList();
    pokemons.forEach(appendPokemon);
    console.log('loaded from network!');
  });

效果

瀏覽器中的不同存儲類型有哪些

你可以在此數(shù)據(jù)庫中存儲數(shù)百兆甚至更多。您可以將所有Pokémon存儲在IndexedDB中,并使其脫機甚至建立索引!這絕對是用于存儲應(yīng)用程序數(shù)據(jù)的一種選擇。

我跳過了第三個示例的實現(xiàn),因為與localStorage 相比,IndexedDB在這種情況下沒有任何區(qū)別。即使使用 IndexedDB,用戶仍然不會與他人分享所選頁面,也不會將其作為書簽供將來使用。它們都不適合這個用例。

Cookies

使用cookies是一種獨特的存儲方式,這是的與服務(wù)器共享的存儲方式。Cookies作為每次請求的一部分被發(fā)送。它可以是當(dāng)用戶瀏覽我們的應(yīng)用程序中的頁面或當(dāng)用戶發(fā)送Ajax請求時。這樣我們就可以在客戶端和服務(wù)器之間建立一個共享狀態(tài),也可以在不同子域的多個應(yīng)用程序之間共享狀態(tài)。本文中介紹的其他存儲選項無法實現(xiàn)。需要注意的是:每個請求都會發(fā)送cookie,這意味著我們必須保持 cookie 較小,以保持適當(dāng)?shù)恼埱蟠笮 ?/p>

Cookies的最常見用途是身份驗證,這不在本文的討論范圍之內(nèi)。就像localStorage 一樣,cookie只能存儲字符串。這些cookie被連接成一個以分號分隔的字符串,并在請求的cookie頭中發(fā)送。你可以為每個cookie設(shè)置很多屬性,比如過期、允許的域名、允許的頁面等等。

在例子中,我展示了如何通過客戶端來操作cookie,但也可以在你的服務(wù)器端應(yīng)用程序中改變它們。

<input type="checkbox" id="darkTheme" name="darkTheme" onclick='onChange(this);'>
<label for="darkTheme">Dark theme</label>
function getCookie(cname) {
  const name = cname + '=';
  const decoded = decodeURIComponent(document.cookie);
  const split = decoded.split(';');
  const relevantCookie = split.find((cookie) => cookie.indexOf(`${cname}=`) === 0);
  if (relevantCookie) {
    return relevantCookie.split('=')[1];
  }
  return null;
}

function toggle(on) {
  if (on) {
    document.documentElement.classList.add('dark'); 
  } else {
    document.documentElement.classList.remove('dark');    
  }
}

function save(on) {
  document.cookie = `dark_theme=${on.toString()}; max-age=31536000; SameSite=None; Secure`;
}

function load() {
  return getCookie('dark_theme') === 'true';
}

function onChange(checkbox) {
  const value = checkbox.checked;
  toggle(value);
  save(value);
}

const initialValue = load();
toggle(initialValue);
document.querySelector('#darkTheme').checked = initialValue;

效果還是跟前面一樣

瀏覽器中的不同存儲類型有哪些

將用戶的喜好保存在cookie中,如果服務(wù)器能夠以某種方式利用它,就可以很好地滿足用戶的需求。例如,在主題用例中,服務(wù)器可以交付相關(guān)的CSS文件,并減少潛在的捆綁大?。ㄔ谖覀冞M行服務(wù)器端渲染的情況下)。另一個用例可能是在沒有數(shù)據(jù)庫的情況下,在多個子域應(yīng)用之間共享這些偏好。

用JavaScript讀寫cookie并不像您想象的那么簡單。要保存新的cookie,您需要設(shè)置document.cookie ——在上面的示例中查看save 函數(shù)。我設(shè)置了dark_theme cookie,并給它添加了一個max-age 屬性,以確保它在關(guān)閉標(biāo)簽時不會過期。另外,我添加SameSiteSecure 屬性。這些都是必要的,因為CodePen使用iframe來運行這些例子,但在大多數(shù)情況下你并不需要它們。讀取一個cookie需要解析cookie字符串。

Cookie字符串如下所示:

key1=value1;key2=value2;key3=value3

因此,首先,我們必須用分號分隔字符串。現(xiàn)在,我們有一個形式為key1=value1 的Cookie數(shù)組,所以我們需要在數(shù)組中找到正確的元素。最后,我們將等號分開并獲得新數(shù)組中的最后一個元素。有點繁瑣,但一旦你實現(xiàn)了getCookie 函數(shù)(或從我的例子中復(fù)制它:P),你就可以忘記它。

將應(yīng)用程序數(shù)據(jù)保存在cookie中可能是個壞主意!它將大大增加請求的大小,并降低應(yīng)用程序性能。此外,服務(wù)器無法從這些信息中獲益,因為它是數(shù)據(jù)庫中已有信息的陳舊版本。如果你使用cookies,請確保它們很小。

分頁示例也不適合cookie,就像localStorageIndexedDB 一樣。當(dāng)前頁面是我們想要與他人共享的臨時狀態(tài),這些方法都無法實現(xiàn)它。

URL storage

URL本身并不是存儲設(shè)備,但它是創(chuàng)建可共享狀態(tài)的好方法。實際上,這意味著將查詢參數(shù)添加到當(dāng)前URL中,這些參數(shù)可用于重新創(chuàng)建當(dāng)前狀態(tài)。好的例子是搜索查詢和過濾器。如果我們在CSS-Tricks上搜索術(shù)語flexbox,則URL將更新為https://css-tricks.com/?s=fle...??纯次覀兪褂肬RL后,分享搜索查詢有多簡單?另一個好處是,你只需點擊刷新按鈕,就可以獲得更新的查詢結(jié)果,甚至可以將其收藏。

我們只能在URL中保存字符串,它的較大長度是有限的,所以我們沒有那么多的空間。我們將不得不保持我們的狀態(tài)小,沒有人喜歡又長又嚇人的網(wǎng)址。

同樣,CodePen使用iframe運行示例,因此您看不到URL實際更改。不用擔(dān)心,因為所有的碎片都在那里,所以你可以在任何你想要的地方使用它。

<input type="checkbox" id="darkTheme" name="darkTheme" onclick='onChange(this);'>
<label for="darkTheme">Dark theme</label>
function toggle(on) {
  if (on) {
    document.documentElement.classList.add('dark'); 
  } else {
    document.documentElement.classList.remove('dark');    
  }
}

function save(on) {
  const params = new URLSearchParams(window.location.search);
  params.set('dark_theme', on.toString());
  history.pushState(null, null, `?${params.toString()}`);
}

function load() {
  const params = new URLSearchParams(window.location.search);
  return params.get('dark_theme') === 'true';
}

function onChange(checkbox) {
  const value = checkbox.checked;
  toggle(value);
  save(value);
}

const initialValue = load();
toggle(initialValue);
document.querySelector('#darkTheme').checked = initialValue;

效果還是一樣

瀏覽器中的不同存儲類型有哪些

我們可以通過window.location.search 訪問查詢字符串,幸運的是,可以使用URLSearchParams 類對其進行解析,無需再應(yīng)用任何復(fù)雜的字符串解析。當(dāng)我們想讀取當(dāng)前值時,可以使用get 函數(shù),當(dāng)我們想寫時,可以使用set。僅設(shè)置值是不夠的,我們還需要更新URL。這可以使用history.pushStatehistory.replaceState 來完成,取決于我們想要完成的行為。

我不建議將用戶的偏好保存在URL中,因為我們必須將這個狀態(tài)添加到用戶訪問的每一個URL中,而且我們無法保證;例如,如果用戶點擊了谷歌搜索的鏈接。

就像Cookie一樣,由于空間太小,我們無法在URL中保存應(yīng)用程序數(shù)據(jù)。而且即使我們真的設(shè)法存儲它,網(wǎng)址也會很長,而且不吸引人點擊??赡芸雌饋硐袷轻烎~攻擊的一種。

<p>Select page:</p>
<p id="pages">
  <button onclick="updatePage(0)">0</button>
  <button onclick="updatePage(1)">1</button>
  <button onclick="updatePage(3)">3</button>
  <button onclick="updatePage(4)">4</button>
  <button onclick="updatePage(5)">5</button>
</p>
<ul id="list">
</ul>
async function loadPokemons(page) {
  const res = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=10&offset=${page * 10}`);
  const data = await res.json();
  return data.results;
}

function appendPokemon(pokemon) {
  const node = document.createElement('li');
  const textnode = document.createTextNode(pokemon.name);
  node.appendChild(textnode);
  document.querySelector('#list').appendChild(node);
}

function clearList() {
  const list = document.querySelector('#list');
  while (list.firstChild) {
    list.removeChild(list.lastChild);
  }
}

function savePage(page) {
  const params = new URLSearchParams(window.location.search);
  params.set('page', page.toString());
  history.pushState(null, null, `?${params.toString()}`);
}

function loadPage() {
  const params = new URLSearchParams(window.location.search);
  if (params.has('page')) {
    return parseInt(params.get('page'));
  }
  return 0;
}

async function updatePage(page) {
  clearList();
  savePage(page);
  const pokemons = await loadPokemons(page);
  pokemons.forEach(appendPokemon);
}

const page = loadPage();
updatePage(page);

效果

瀏覽器中的不同存儲類型有哪些

就像我們的分頁例子一樣,臨時應(yīng)用狀態(tài)是最適合URL查詢字符串的。同樣,你無法看到URL的變化,但每次點擊一個頁面時,URL都會以?page=x 查詢參數(shù)更新。當(dāng)網(wǎng)頁加載時,它會查找這個查詢參數(shù),并相應(yīng)地獲取正確的頁面?,F(xiàn)在,我們可以把這個網(wǎng)址分享給我們的朋友,讓他們可以享受我們最喜歡的神奇寶貝。

Cache API

Cache API是網(wǎng)絡(luò)級的存儲,它用于緩存網(wǎng)絡(luò)請求及其響應(yīng)。Cache API非常適合service worker,service worker可以攔截每一個網(wǎng)絡(luò)請求,使用 Cache API 它可以輕松地緩存這兩個請求。service worker也可以將現(xiàn)有的緩存項作為網(wǎng)絡(luò)響應(yīng)返回,而不是從服務(wù)器上獲取。這樣,您可以減少網(wǎng)絡(luò)負(fù)載時間,并使你的應(yīng)用程序即使處于脫機狀態(tài)也能正常工作。最初,它是為service worker創(chuàng)建的,但在現(xiàn)代瀏覽器中,Cache API也可以在窗口、iframe和worker上下文中使用。這是一個非常強大的API,可以極大地改善應(yīng)用的用戶體驗。

就像IndexedDB一樣,Cache API的存儲不受限制,您可以存儲數(shù)百兆字節(jié),如果需要甚至可以存儲更多。API是異步的,所以它不會阻塞你的主線程,而且它可以通過全局屬性caches 來訪問。

Browser extension

如果你建立一個瀏覽器擴展,你有另一個選擇來存儲你的數(shù)據(jù),我在進行擴展程序daily.dev時發(fā)現(xiàn)了它。如果你使用Mozilla的polyfill,它可以通過chrome.storagebrowser.storage 獲得。確保在你的清單中申請一個存儲權(quán)限以獲得訪問權(quán)。

有兩種類型的存儲選項:local和sync。local存儲是不言而喻的,它的意思是不共享,保存在本地。sync存儲是作為谷歌賬戶的一部分同步的,你在任何地方用同一個賬戶安裝擴展,這個存儲都會被同步。兩者都有相同的API,所以如果需要的話,來回切換超級容易。它是異步存儲,因此不會像localStorage 這樣阻塞主線程。不幸的是,我不能為這個存儲選項創(chuàng)建一個演示,因為它需要一個瀏覽器擴展,但它的使用非常簡單,幾乎和localStorage 一樣。有關(guān)確切實現(xiàn)的更多信息,請參閱Chrome文檔。

結(jié)束

瀏覽器有許多選項可用于存儲數(shù)據(jù)。根據(jù)Chrome團隊的建議,我們的選存儲應(yīng)該是IndexedDB,它是異步存儲,有足夠的空間來存儲我們想要的任何東西。不鼓勵使用localStorage,但它比IndexedDB 更易于使用。Cookies是與服務(wù)器共享客戶端狀態(tài)的一種好方法,但通常用于身份驗證。

如果你想創(chuàng)建具有可共享狀態(tài)的頁面,如搜索頁面,請使用URL的查詢字符串來存儲這些信息。最后,如果你建立一個擴展,一定要閱讀關(guān)于chrome.storage

看完了這篇文章,相信你對瀏覽器中的不同存儲類型有哪些有了一定的了解,想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

網(wǎng)站名稱:瀏覽器中的不同存儲類型有哪些-創(chuàng)新互聯(lián)
文章源于:http://muchs.cn/article22/csgjcc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作、微信小程序定制開發(fā)、手機網(wǎng)站建設(shè)、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設(shè)計