Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
nenote是微軟一款可以整理、組織并數(shù)字化絕大多數(shù)資料,例如文字、圖片、表格、錄音、錄像等的工具。Onenote可以隨時(shí)隨地將你需要的信息進(jìn)行收錄,而且還能實(shí)現(xiàn)脫機(jī)編輯和隨后的同步合并,是一款非常強(qiáng)大的工具。
有的時(shí)候我們?yōu)g覽網(wǎng)頁(yè),看到非常有用的信息時(shí),會(huì)希望立即把它記下來。Onenote支持在網(wǎng)頁(yè)上直接做筆記,加注釋,設(shè)置手寫筆記保存哦!
借助Windows10的新瀏覽器MicrosoftEdge,您可以在網(wǎng)頁(yè)上用鼠標(biāo)書寫筆記、添加注釋,在支持觸摸的設(shè)備上手寫筆記。記錄完成后可以共享到OneNote。
打開MicrosoftEdge瀏覽器,瀏覽某個(gè)網(wǎng)頁(yè)時(shí),如果你想要開始記錄,單擊右上角的圖標(biāo),進(jìn)入筆記狀態(tài)。
左上角的各個(gè)圖標(biāo),可進(jìn)行墨跡書寫、涂畫、截圖和擦除墨跡等不同的操作。
筆記記錄完成后,單擊右上角的保存或共享圖標(biāo),可以將筆記保存或共享至OneNote。
OneNoteClipper可將網(wǎng)頁(yè)內(nèi)容直接剪輯到OneNote中。可以選擇剪輯整個(gè)頁(yè)面或只剪輯文章,還可以選擇保存位置。Clipper是一款免費(fèi)應(yīng)用,可在應(yīng)用商店里獲取。
打開Clipper后,單擊“剪輯至OneNote”。
按Ctrl+Shift+B,打開收藏夾欄。右鍵單擊“剪輯至OneNote”,選擇“添加到收藏夾”。
在瀏覽網(wǎng)頁(yè)時(shí),看到希望收集的內(nèi)容后,在IE瀏覽器的收藏夾欄,單擊“剪輯至OneNote”,再單擊“登錄”。
用Office365賬號(hào)或微軟賬號(hào)登錄。
再次在IE瀏覽器的收藏夾欄單擊“剪輯至OneNote”,在彈出的窗口中可選擇整頁(yè)或文章,并可指定保存位置。單擊“剪輯”,網(wǎng)頁(yè)內(nèi)容被收集到OneNote中。
訪問您的OneNote筆記,可查看收集的網(wǎng)頁(yè)內(nèi)容。
通過集成在IE瀏覽器中的“發(fā)送至OneNote”這一功能,我們能夠在任何網(wǎng)頁(yè)中迅速捕捉到需要的信息和資料,并收集到筆記中。
在IE瀏覽器中,從網(wǎng)頁(yè)中選取內(nèi)容,單擊鼠標(biāo)右鍵,選擇“SendtoOneNote”。
在對(duì)話框中,選擇要存放內(nèi)容的分區(qū),并單擊“確定”。
內(nèi)容將直接存儲(chǔ)在筆記頁(yè)中,并在末尾插入來源網(wǎng)頁(yè)鏈接,以后可單擊此鏈接再次訪問相應(yīng)的網(wǎng)頁(yè)。
學(xué)會(huì)了嗎?趕緊試試吧!
家好,Echa。
今天來分享常見的瀏覽器數(shù)據(jù)存儲(chǔ)方案:localStorage、sessionStorage、IndexedDB、Cookies。
現(xiàn)代瀏覽器中提供了多種存儲(chǔ)機(jī)制,打開瀏覽器的控制臺(tái)(Mac 可以使用 Command + Option + J 快捷鍵,Windows 可以使用 Control + Shift + J 快捷鍵)。選擇 Application 選項(xiàng)卡,可以在 Storage中 看到 Local Storage、Session Storage、IndexedDB、Web SQL、Cookies 等:
那數(shù)據(jù)存儲(chǔ)在瀏覽器中有什么使用場(chǎng)景呢?在以下情況下,將數(shù)據(jù)存儲(chǔ)在瀏覽器中成為更可行的選擇:
無(wú)論哪種方式,將這些信息保存在客戶端可以減少額外且不必要的服務(wù)器調(diào)用,并幫助提供離線支持。不過,需要注意,由于實(shí)現(xiàn)差異,瀏覽器存儲(chǔ)機(jī)制在不同瀏覽器中的行為可能會(huì)有所不同。除此之外,許多瀏覽器已刪除對(duì) Web SQL 的支持,建議將現(xiàn)有用法遷移到 IndexedDB。
所以下面我們將介紹 Local Storage、Session Storage、IndexedDB、Cookies 的使用方式、使用場(chǎng)景以及它們之間的區(qū)別。
HTML5 引入了 Web Storage,這使得在瀏覽器中存儲(chǔ)和檢索數(shù)據(jù)變得更加容易。Web Storage API 為客戶端瀏覽器提供了安全存儲(chǔ)和輕松訪問鍵值對(duì)的機(jī)制。Web Storage 提供了兩個(gè) API 來獲取和設(shè)置純字符串的鍵值對(duì):
Web Storage API 由 4 個(gè)方法 setItem()、getItem()、removeItem() 、clear()、key()和一個(gè) length 屬性組成,以 localStorage 為例:
console.log(typeof window.localStorage) // Object
// 存儲(chǔ)數(shù)據(jù)
localStorage.setItem("colorMode", "dark")
localStorage.setItem("username", "zhangsan")
localStorage.setItem("favColor", "green")
console.log(localStorage.length) // 3
// 檢索數(shù)據(jù)
console.log(localStorage.getItem("colorMode")) // dark
// 移除數(shù)據(jù)
localStorage.removeItem("colorMode")
console.log(localStorage.length) // 2
console.log(localStorage.getItem("colorMode")) // null
// 檢索鍵名
window.localStorage.key(0); // favColor
// 清空本地存儲(chǔ)
localStorage.clear()
console.log(localStorage.length) // 0
localStorage 和 sessionStorage 都非常適合緩存非敏感應(yīng)用數(shù)據(jù)。可以在需要存儲(chǔ)少量簡(jiǎn)單值并不經(jīng)常訪問它們是使用它們。它們本質(zhì)上都是同步的,并且會(huì)阻塞主 UI 線程,所以應(yīng)該謹(jǐn)慎使用。
我們可以在瀏覽器上監(jiān)聽 localStorage 和 sessionStorage 的存儲(chǔ)變化。storage 事件在創(chuàng)建、刪除或更新項(xiàng)目時(shí)觸發(fā)。偵聽器函數(shù)在事件中傳遞,具有以下屬性:
通常,我們可以使用 window.addEventListener("storage", func) 或使用 onstorage 屬性(如 window.onstorage=func)來監(jiān)聽 storage 事件:
window.addEventListener('storage', e=> {
console.log(e.key);
console.log(e.oldValu);
console.log(e.newValue);
});
window.onstorage=e=> {
console.log(e.key);
console.log(e.oldValu);
console.log(e.newValue);
});
注意,該功能不會(huì)在發(fā)生更改的同一瀏覽器選項(xiàng)卡上觸發(fā),而是由同一域的其他打開的選項(xiàng)卡或窗口觸發(fā)。此功能用于同步同一域的所有瀏覽器選項(xiàng)卡/窗口上的數(shù)據(jù)。因此,要對(duì)此進(jìn)行測(cè)試,需要打開同一域的另一個(gè)選項(xiàng)卡。
localStorage 和 sessionStorage 只能存儲(chǔ) 5 MB 的數(shù)據(jù),因此需要確保存儲(chǔ)的數(shù)據(jù)不會(huì)超過此限制。
localStorage.setItem('a', Array(1024 * 1024 * 5).join('a'))
localStorage.setItem('b', 'a')
// Uncaught DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of `a` exceeded the quota.
在上面的例子中,收到了一個(gè)錯(cuò)誤,首先創(chuàng)建了一個(gè)5MB的大字符串,當(dāng)再添加其他數(shù)據(jù)時(shí)就報(bào)錯(cuò)了。
另外,localStorage 和 sessionStorage 只接受字符串。可以通過 JSON.stringify 和 JSON.parse 來解決這個(gè)問題:
const user={
name : "zhangsan",
age : 28,
gender : "male",
profession : "lawyer"
};
localStorage.setItem("user", JSON.stringify(user));
localStorage.getItem("user"); // '{"name":"zhangsan","age":28,"gender":"male","profession":"lawyer"}'
JSON.parse(localStorage.getItem("user")) // {name: 'zhangsan', age: 28, gender: 'male', profession: 'lawyer'}
如果我們直接將一個(gè)對(duì)象存儲(chǔ)在 localStorage 中,那將會(huì)在存儲(chǔ)之前進(jìn)行隱式類型轉(zhuǎn)換,將對(duì)象轉(zhuǎn)換為字符串,再進(jìn)行存儲(chǔ):
const user={
name : "zhangsan",
age : 28,
gender : "male",
profession : "lawyer"
};
localStorage.setItem("user", user);
localStorage.getItem("user"); // '[object Object]'
Web Storage 使用了同源策略,也就是說,存儲(chǔ)的數(shù)據(jù)只能在同一來源上可用。如果域和子域相同,則可以從不同的選項(xiàng)卡訪問 localStorage 數(shù)據(jù),而無(wú)法訪問 sessionStorage 數(shù)據(jù),即使它是完全相同的頁(yè)面。
另外:
下面來看一個(gè)使用 localStorage 的簡(jiǎn)單示例,使用 localStorage 來存儲(chǔ)用戶偏好:
<input type="checkbox" id="darkTheme" name="darkTheme" onclick='onChange(this);'>
<label for="darkTheme">黑暗模式</label><br>
html {
background: white;
}
.dark {
background: black;
color: white;
}
function toggle(on) {
if (on) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}
function save(on) {
localStorage.setItem('darkTheme', on.toString());
}
function load() {
return localStorage.getItem('darkTheme')==='true';
}
function onChange(checkbox) {
const value=checkbox.checked;
toggle(value);
save(value);
}
const initialValue=load();
toggle(initialValue);
document.querySelector('#darkTheme').checked=initialValue;
這里的代碼很簡(jiǎn)單,頁(yè)面上有一個(gè)單選框,選中按鈕時(shí)將頁(yè)面切換為黑暗模式,并將這個(gè)配置存儲(chǔ)在 localStorage 中。當(dāng)下一次再初始頁(yè)面時(shí),獲取 localStorage 中的主題設(shè)置。
Cookie 主要用于身份驗(yàn)證和用戶數(shù)據(jù)持久性。Cookie 與請(qǐng)求一起發(fā)送到服務(wù)器,并在響應(yīng)時(shí)發(fā)送到客戶端;因此,cookies 數(shù)據(jù)在每次請(qǐng)求時(shí)都會(huì)與服務(wù)器交換。服務(wù)器可以使用 cookie 數(shù)據(jù)向用戶發(fā)送個(gè)性化內(nèi)容。嚴(yán)格來說,cookie 并不是客戶端存儲(chǔ)方式,因?yàn)榉?wù)器和瀏覽器都可以修改數(shù)據(jù)。它是唯一可以在一段時(shí)間后自動(dòng)使數(shù)據(jù)過期的方式。
每個(gè) HTTP 請(qǐng)求和響應(yīng)都會(huì)發(fā)送 cookie 數(shù)據(jù)。存儲(chǔ)過多的數(shù)據(jù)會(huì)使 HTTP 請(qǐng)求更加冗長(zhǎng),從而使應(yīng)用比預(yù)期更慢:
Cookie 通常用于會(huì)話管理、個(gè)性化以及跨網(wǎng)站跟蹤用戶行為。我們可以通過服務(wù)端和客戶端設(shè)置和訪問 cookie。Cookie 還具有各種屬性,這些屬性決定了在何處以及如何訪問和修改它們,
Cookie 分為兩種類型:
下面先來看看如何訪問和操作客戶端和服務(wù)器上的 cookie。
客戶端 JavaScript 可以通過 document.cookie 來讀取當(dāng)前位置可訪問的所有 cookie。它提供了一個(gè)字符串,其中包含一個(gè)以分號(hào)分隔的 cookie 列表,使用 key=value 格式。
document.cookie;
可以看到,在語(yǔ)雀主頁(yè)中獲取 cookie,結(jié)果中包含了登錄的 cookie、語(yǔ)言、當(dāng)前主題等。
同樣,可以使用 document.cookie 來設(shè)置 cookie 的值,設(shè)置cookie也是用key=value格式的字符串,屬性用分號(hào)隔開:
document.cookie="hello=world; domain=example.com; Secure";
這里用到了兩個(gè)屬性 SameSite 和 Secure,下面會(huì)介紹。如果已經(jīng)存在同名的 cookie 屬性,就會(huì)更新已有的屬性值,如果不存在,就會(huì)創(chuàng)建一個(gè)新的 key=value。
如果需要經(jīng)常在客戶端處理 Cookie,建議使用像 js-cookie 這樣的庫(kù)來處理客戶端 cookie:
Cookies.set('hello', 'world', { domain: 'example.com', secure: true });
Cookies.get('hello'); // -> world
這樣不僅為 cookie 上的 CRUD 操作提供了一個(gè)干凈的 API,而且還支持 TypeScript,從而幫助避免屬性的拼寫錯(cuò)誤。
服務(wù)端可以通過 HTTP 請(qǐng)求的請(qǐng)求頭和響應(yīng)頭來訪問和修改 cookie。每當(dāng)瀏覽器向服務(wù)端發(fā)送 HTTP 請(qǐng)求時(shí),它都會(huì)使用 cookie 頭將所有相關(guān) cookie 都附加到該站點(diǎn)。請(qǐng)求標(biāo)頭是一個(gè)分號(hào)分隔的字符串。
這樣就可以從請(qǐng)求頭中讀取這些 cookie。如果在服務(wù)端使用 Node.js,可以像下面這樣從請(qǐng)求對(duì)象中讀取它們,將獲得以分號(hào)分隔的 key=value 對(duì):
http.createServer(function (request, response) {
const cookies=request.headers.cookie;
// "cookie1=value1; cookie2=value2"
...
}).listen(8124);
如果想要設(shè)置 cookie,可以在響應(yīng)頭中添加 Set-Cookie 頭,其中 cookie 采用 key=value 的格式,屬性用分號(hào)分隔:
response.writeHead(200, {
'Set-Cookie': 'mycookie=test; domain=example.com; Secure'
});
通常我們不會(huì)直接編寫 Node.js,而是與 ExpressJS 這樣的 Node.js 框架一起使用。使用 Express 可以更輕松地訪問和修改 cookie。只需添加一個(gè)像 cookie-parser 這樣的中間件,就可以通過 req.cookies 以 JavaScript 對(duì)象的形式獲得所有的 cookie。還可以使用 Express 內(nèi)置的 res.cookie() 方法來設(shè)置 cookie:
const express=require('express')
const cookieParser=require('cookie-parser')
const app=express()
app.use(cookieParser())
app.get('/', function (req, res) {
console.log('Cookies: ', req.cookies)
// Cookies: { cookie1: 'value1', cookie2: 'value2' }
res.cookie('name', 'tobi', { domain: 'example.com', secure: true })
})
app.listen(8080)
下面來深入了解 cookie 的屬性。除了名稱和值之外,cookie 還具有控制很多方面的屬性,包括安全方面、生命周期以及它們?cè)跒g覽器中的訪問位置和方式等。
Domain 屬性告訴瀏覽器允許哪些主機(jī)訪問 cookie。如果未指定,則默認(rèn)為設(shè)置 cookie 的同一主機(jī)。因此,當(dāng)使用客戶端 JavaScript 訪問 cookie 時(shí),只能訪問與 URL 域相同的 cookie。同樣,只有與 HTTP 請(qǐng)求的域共享相同域的 cookie 可以與請(qǐng)求頭一起發(fā)送到服務(wù)端。
注意,擁有此屬性并不意味著可以為任何域設(shè)置 cookie,因?yàn)檫@顯然會(huì)帶來巨大的安全風(fēng)險(xiǎn)。此屬性存在的唯一原因就是減少域的限制并使 cookie 在子域上可訪問。例如,如果當(dāng)前的域是 abc.xyz.com,并且在設(shè)置 cookie 時(shí)如果不指定 Domain 屬性,則默認(rèn)為 abc.xyz.com,并且 cookie 將僅限于該域。但是,可能希望相同的 cookie 也可用于其他子域,因此可以設(shè)置 Domain=xyz.com 以使其可用于其他子域,如 def.xyz.com 和主域 xyz.com。
此屬性指定訪問 cookie 必須存在的請(qǐng)求 URL 中的路徑。除了將 cookie 限制到域之外,還可以通過路徑來限制它。路徑屬性為 Path=/store 的 cookie 只能在路徑 /store 及其子路徑 /store/cart、/store/gadgets 等上訪問。
該屬性用來設(shè)置 cookie 的過期時(shí)間。若設(shè)置其值為一個(gè)時(shí)間,那么當(dāng)?shù)竭_(dá)此時(shí)間后,cookie 就會(huì)失效。不設(shè)置的話默認(rèn)值是 Session,意思是cookie會(huì)和session一起失效。當(dāng)瀏覽器關(guān)閉(不是瀏覽器標(biāo)簽頁(yè)) 后,cookie 就會(huì)失效。
除此之外,它還可以通過將過期日期設(shè)置為過去來刪除 cookie。
具有 Secure 屬性的 cookie 僅可以通過安全的 HTTPS 協(xié)議發(fā)送到服務(wù)器,而不會(huì)通過 HTTP 協(xié)議。這有助于通過使 cookie 無(wú)法通過不安全的連接訪問來防止中間人攻擊。除非網(wǎng)站實(shí)用不安全的 HTTP 連接,否則應(yīng)該始終將此屬性與所有 cookie 一起使用。
此屬性使 cookie 只能通過服務(wù)端訪問。因此,只有服務(wù)斷可以通過響應(yīng)頭設(shè)置它們,然后瀏覽器會(huì)將它們與每個(gè)后續(xù)請(qǐng)求的頭一起發(fā)送到服務(wù)器,并且它們將無(wú)法通過客戶端 JavaScript 訪問。
這可以在一定程度上幫助保護(hù)帶有敏感信息(如身份驗(yàn)證 token)的 cookie 免受 XSS 攻擊,因?yàn)槿魏慰蛻舳四_本都無(wú)法讀取 cookie。但這并不意味著可以完全免受 XSS 攻擊。因?yàn)椋绻粽呖梢栽诰W(wǎng)站上執(zhí)行第三方腳本,那可能無(wú)法訪問 cookie,相反,他們可以直接向服務(wù)端執(zhí)行相關(guān)的 API 請(qǐng)求。因此,想象一下用戶訪問了一個(gè)頁(yè)面,黑客在網(wǎng)站上注入了惡意腳本。他們可以使用該腳本執(zhí)行任何 API,并在他們不知道的情況下代表用戶執(zhí)行操作。
Js Cookie 是一個(gè)簡(jiǎn)單、輕量級(jí)的 JavaScript API,用于處理瀏覽器 cookie。其支持 AMD、CommonJS 和 ES 模塊、沒有依賴關(guān)系、經(jīng)過徹底測(cè)試、支持自定義編碼和解碼、通用瀏覽器支持。
安裝:
npm i js-cookie
使用:
// 設(shè)置 Cookie
Cookies.set('cookie-name', 'cookie-value', { expires: 14})
// 讀取 Cookie
Cookies.get('cookie-name')
// 刪除 Cookie
Cookies.remove('cookie-name')
React Cookie 是一個(gè)專門用于 React 的 cookie 庫(kù),它繼承了 Universal Cookie 庫(kù)的功能。它提供了一組組件和 Hooks,使 React 中的 cookie 處理非常簡(jiǎn)單。如果使用的是 React 16.8+ 版本,就可以使用 hooks 來處理 cookie。否則,必須使用其提供的組件。
安裝:
npm i react-cookie
React Cookie 提供了 3 個(gè) Hook,分別是 cookie、setCookie 和 removeCookie。可以使用這些 Hook 來處理 React 應(yīng)用中的 cookie。
const [cookies, setCookie, removeCookie]=useCookies(['cookie-name']);
// 設(shè)置 Cookie
setCookie(name, value, [options]);
// 刪除 Cookie
removeCookie(name, [options])
Cookies 是用于 HTTP cookie 配置的流行 NodeJS 模塊之一。可以輕松地將其與內(nèi)置的 NodeJS HTTP 庫(kù)集成或?qū)⑵溆米?Express 中間件。它允許使用 Keygrip 對(duì) cookie 進(jìn)行簽名以防止篡改、支持延遲 cookie 驗(yàn)證、不允許通過不安全的套接字發(fā)送安全 cookie、允許其他庫(kù)在不知道簽名機(jī)制的情況下訪問 cookie。
安裝:
npm install cookies
使用:
const cookie=require('cookie');
cookies=new Cookies( request, response, [ options ] )
// 讀取 cookies
cookies.get( name, [ options ] )
// 設(shè)置 cookies
cookies.set( name, [ value ], [ options ] )
IndexedDB 提供了一個(gè)類似 NoSQL 的 key/value 數(shù)據(jù)庫(kù),它可以存儲(chǔ)大量結(jié)構(gòu)化數(shù)據(jù),甚至是文件和 blob。每個(gè)域至少有 1GB 的可用空間,并且最多可以達(dá)到剩余磁盤空間的 60%。
IndexedDB 于 2011 年首次實(shí)現(xiàn),并于 2015 年 1 月成為 W3C 標(biāo)準(zhǔn),它具有良好的瀏覽器支持:
key/value 數(shù)據(jù)庫(kù)意味著存儲(chǔ)的所有數(shù)據(jù)都必須分配給一個(gè) key。它將key 與 value 相關(guān)聯(lián),key 用作該值的唯一標(biāo)識(shí)符,這意味著可以使用該 key 跟蹤該值。如果應(yīng)用需要不斷獲取數(shù)據(jù),key/value 數(shù)據(jù)庫(kù)使用非常高效且緊湊的索引結(jié)構(gòu)來快速可靠地通過 key 定位值。使用該 key,不僅可以檢索存儲(chǔ)的值,還可以刪除、更新和替換該值。
在說 IndexedDB 之前,先來看一些相關(guān)術(shù)語(yǔ):
indexedDB 特點(diǎn)如下:
IndexedDB 使用場(chǎng)景:
不同瀏覽器的 IndexedDB 可能使用不同的名稱。可以使用以下方法檢查 IndexedDB 支持:
const indexedDB=window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB ||
window.shimIndexedDB;
if (!indexedDB) {
console.log("不支持 IndexedDB");
}
可以使用 indexedDB.open() 來連接數(shù)據(jù)庫(kù):
const dbOpen=indexedDB.open('performance', 1);
indexedDB.open 的第一個(gè)參數(shù)是數(shù)據(jù)庫(kù)名稱,第二個(gè)參數(shù)是可選的版本整數(shù)。
可以使用以下三個(gè)事件處理函數(shù)監(jiān)聽 indexedDB 的連接狀態(tài):
在無(wú)法建立 IndexedDB 連接時(shí),將觸發(fā)該事件:
// 連接失敗
dbOpen.onerror=e=> {
reject(`IndexedDB error: ${ e.target.errorCode }`);
};
如果在無(wú)痕模式、隱私模式下運(yùn)行瀏覽器,可能不支持 IndexedDB,需要禁用這些模式。
一旦數(shù)據(jù)庫(kù)連接打開,就會(huì)觸發(fā) onupgradeneeded 事件,該事件可用于創(chuàng)建 object store。
dbOpen.onupgradeneeded=e=> {
const db=dbOpen.result;
// 創(chuàng)建 object store
const store=db.createObjectStore("cars", { keyPath: "id" });
// 使用自動(dòng)遞增的id
// const store=db.createObjectStore('cars', { autoIncrement: true });
// 創(chuàng)建索引
store.createIndex("cars_colour", ["colour"], {
unique: true
});
// 創(chuàng)建復(fù)合索引
store.createIndex("colour_and_make", ["colour", "make"], {
unique: false,
});
};
IndexedDB 使用了 object store 的概念,其本質(zhì)上是數(shù)據(jù)集合的名稱。可以在單個(gè)數(shù)據(jù)庫(kù)中創(chuàng)建任意數(shù)量的 object store。keyPath是 IndexedDB 將用來識(shí)別對(duì)象字段名稱,通常是一個(gè)唯一的編號(hào),也可以通過 autoIncrement: true 來自動(dòng)為 store 設(shè)置唯一遞增的 ID。除了普通的索引,還可以創(chuàng)建復(fù)合索引,使用多個(gè)關(guān)鍵詞的組合進(jìn)行查詢。
在連接建立并且所有升級(jí)都完成時(shí),將觸發(fā)該事件。上面我們已經(jīng)新建了 schema,接下來就可以在onsuccess 中添加、查詢數(shù)據(jù)。
// 連接成功
dbOpen.onsuccess=()=> {
this.db=dbOpen.result;
//1
const transaction=db.transaction("cars", "readwrite");
//2
const store=transaction.objectStore("cars");
const colourIndex=store.index("cars_colour");
const makeModelIndex=store.index("colour_and_make");
//3
store.put({ id: 1, colour: "Red", make: "Toyota" });
store.put({ id: 2, colour: "Red", make: "Kia" });
store.put({ id: 3, colour: "Blue", make: "Honda" });
store.put({ id: 4, colour: "Silver", make: "Subaru" });
//4
const idQuery=store.get(4);
const colourQuery=colourIndex.getAll(["Red"]);
const colourMakeQuery=makeModelIndex.get(["Blue", "Honda"]);
// 5
idQuery.onsuccess=function () {
console.log('idQuery', idQuery.result);
};
colourQuery.onsuccess=function () {
console.log('colourQuery', colourQuery.result);
};
colourMakeQuery.onsuccess=function () {
console.log('colourMakeQuery', colourMakeQuery.result);
};
// 6
transaction.oncomplete=function () {
db.close();
};
};
這里總共有六部分:
運(yùn)行上面的代碼,就會(huì)得到以下結(jié)果:
可以在 Chrome Devtools 中查看:
下面來看看如何更新和刪除數(shù)據(jù)。
const subaru=store.get(4);
subaru.onsuccess=function () {
subaru.result.colour="Green";
store.put(subaru.result);
}
這會(huì)將數(shù)據(jù)庫(kù)中 Silver 色的 Subaru 的顏色更新為綠色。
const deleteCar=store.delete(1);
deleteCar.onsuccess=function () {
console.log("Removed");
};
如果不知道 key 并且希望根據(jù)值來刪除,可以這樣:
const redCarKey=colourIndex.getKey(["Red"]);
redCarKey.onsuccess=function () {
const deleteCar=store.delete(redCarKey.result);
deleteCar.onsuccess=function () {
console.log("Removed");
};
};
結(jié)果如下:
可以使用基于 Promise 的 Storage API 檢查 Web Storage、IndexedDB 和 Cache API 的剩余空間。異步 .estimate() 方法返回:
(async ()=> {
if (!navigator.storage) return;
const storage=await navigator.storage.estimate();
console.log(`可用大小: ${ storage.quota / 1024 } Kb`);
console.log(`已用大小: ${ storage.usage / 1024 } Kb`);
console.log(`已用占比: ${ Math.round((storage.usage / storage.quota) * 100) }%`);
console.log(`剩余大小: ${ Math.floor((storage.quota - storage.usage) / 1024) } Kb`);
})();
Storage API 的瀏覽器兼容性如下:
言
本篇文章主要介紹了前端HTML5幾種存儲(chǔ)方式的總結(jié) ,主要包括本地存儲(chǔ)localstorage,本地存儲(chǔ)sessionstorage,離線緩存(application cache),Web SQL,IndexedDB。有興趣的可以了解一下。
正文開始~
總體情況
h5之前,存儲(chǔ)主要是用cookies。cookies缺點(diǎn)有在請(qǐng)求頭上帶著數(shù)據(jù),大小是4k之內(nèi)。主Domain污染。
主要應(yīng)用:購(gòu)物車、客戶登錄
對(duì)于IE瀏覽器有UserData,大小是64k,只有IE瀏覽器支持。
目標(biāo)
存儲(chǔ)方式:
以鍵值對(duì)(Key-Value)的方式存儲(chǔ),永久存儲(chǔ),永不失效,除非手動(dòng)刪除。
大小:
每個(gè)域名5M
支持情況:
注意:IE9 localStorage不支持本地文件,需要將項(xiàng)目署到服務(wù)器,才可以支持!
if(window.localStorage){ alert('This browser supports localStorage'); }else{ alert('This browser does NOT support localStorage'); }
常用的API:
getItem //取記錄
setIten//設(shè)置記錄
removeItem//移除記錄
key//取key所對(duì)應(yīng)的值
clear//清除記錄
存儲(chǔ)的內(nèi)容:
數(shù)組,圖片,json,樣式,腳本。。。(只要是能序列化成字符串的內(nèi)容都可以存儲(chǔ))
2.本地存儲(chǔ)sessionstorage
HTML5 的本地存儲(chǔ) API 中的 localStorage 與 sessionStorage 在使用方法上是相同的,區(qū)別在于 sessionStorage 在關(guān)閉頁(yè)面后即被清空,而 localStorage 則會(huì)一直保存。
3.離線緩存(application cache)
本地緩存應(yīng)用所需的文件
使用方法:
①配置manifest文件
頁(yè)面上:
<!DOCTYPE HTML> <html manifest="demo.appcache"> ... </html>
Manifest 文件:
manifest 文件是簡(jiǎn)單的文本文件,它告知瀏覽器被緩存的內(nèi)容(以及不緩存的內(nèi)容)。
manifest 文件可分為三個(gè)部分:
①CACHE MANIFEST - 在此標(biāo)題下列出的文件將在首次下載后進(jìn)行緩存
②NETWORK - 在此標(biāo)題下列出的文件需要與服務(wù)器的連接,且不會(huì)被緩存
③FALLBACK - 在此標(biāo)題下列出的文件規(guī)定當(dāng)頁(yè)面無(wú)法訪問時(shí)的回退頁(yè)面(比如 404 頁(yè)面)
完整demo:
CACHE MANIFEST # 2016-07-24 v1.0.0 /theme.css /main.js NETWORK: login.jsp FALLBACK: /html/ /offline.html
服務(wù)器上:manifest文件需要配置正確的MIME-type,即 "text/cache-manifest"。
如Tomcat:
<mime-mapping> <extension>manifest</extension> <mime-type>text/cache-manifest</mime-type> </mime-mapping>
常用API:
核心是applicationCache對(duì)象,有個(gè)status屬性,表示應(yīng)用緩存的當(dāng)前狀態(tài):
0(UNCACHED) : 無(wú)緩存, 即沒有與頁(yè)面相關(guān)的應(yīng)用緩存
1(IDLE) : 閑置,即應(yīng)用緩存未得到更新
2 (CHECKING) : 檢查中,即正在下載描述文件并檢查更新
3 (DOWNLOADING) : 下載中,即應(yīng)用緩存正在下載描述文件中指定的資源
4 (UPDATEREADY) : 更新完成,所有資源都已下載完畢
5 (IDLE) : 廢棄,即應(yīng)用緩存的描述文件已經(jīng)不存在了,因此頁(yè)面無(wú)法再訪問應(yīng)用緩存
相關(guān)的事件:
表示應(yīng)用緩存狀態(tài)的改變:
checking : 在瀏覽器為應(yīng)用緩存查找更新時(shí)觸發(fā)
error : 在檢查更新或下載資源期間發(fā)送錯(cuò)誤時(shí)觸發(fā)
noupdate : 在檢查描述文件發(fā)現(xiàn)文件無(wú)變化時(shí)觸發(fā)
downloading : 在開始下載應(yīng)用緩存資源時(shí)觸發(fā)
progress:在文件下載應(yīng)用緩存的過程中持續(xù)不斷地下載地觸發(fā)
updateready : 在頁(yè)面新的應(yīng)用緩存下載完畢觸發(fā)
cached : 在應(yīng)用緩存完整可用時(shí)觸發(fā)
Application Cache的三個(gè)優(yōu)勢(shì):
① 離線瀏覽
② 提升頁(yè)面載入速度
③ 降低服務(wù)器壓力
注意事項(xiàng):
1. 瀏覽器對(duì)緩存數(shù)據(jù)的容量限制可能不太一樣(某些瀏覽器設(shè)置的限制是每個(gè)站點(diǎn) 5MB)
2. 如果manifest文件,或者內(nèi)部列舉的某一個(gè)文件不能正常下載,整個(gè)更新過程將視為失敗,瀏覽器繼續(xù)全部使用老的緩存
3. 引用manifest的html必須與manifest文件同源,在同一個(gè)域下
4. 瀏覽器會(huì)自動(dòng)緩存引用manifest文件的HTML文件,這就導(dǎo)致如果改了HTML內(nèi)容,也需要更新版本才能做到更新。
5. manifest文件中CACHE則與NETWORK,F(xiàn)ALLBACK的位置順序沒有關(guān)系,如果是隱式聲明需要在最前面
6. FALLBACK中的資源必須和manifest文件同源
7. 更新完版本后,必須刷新一次才會(huì)啟動(dòng)新版本(會(huì)出現(xiàn)重刷一次頁(yè)面的情況),需要添加監(jiān)聽版本事件。
8. 站點(diǎn)中的其他頁(yè)面即使沒有設(shè)置manifest屬性,請(qǐng)求的資源如果在緩存中也從緩存中訪問
9. 當(dāng)manifest文件發(fā)生改變時(shí),資源請(qǐng)求本身也會(huì)觸發(fā)更新
離線緩存與傳統(tǒng)瀏覽器緩存區(qū)別:
1. 離線緩存是針對(duì)整個(gè)應(yīng)用,瀏覽器緩存是單個(gè)文件
2. 離線緩存斷網(wǎng)了還是可以打開頁(yè)面,瀏覽器緩存不行
3. 離線緩存可以主動(dòng)通知瀏覽器更新資源
4.Web SQL
關(guān)系數(shù)據(jù)庫(kù),通過SQL語(yǔ)句訪問
Web SQL 數(shù)據(jù)庫(kù) API 并不是 HTML5 規(guī)范的一部分,但是它是一個(gè)獨(dú)立的規(guī)范,引入了一組使用 SQL 操作客戶端數(shù)據(jù)庫(kù)的 APIs。
支持情況:
Web SQL 數(shù)據(jù)庫(kù)可以在最新版的 Safari, Chrome 和 Opera 瀏覽器中工作。
核心方法:
①openDatabase:這個(gè)方法使用現(xiàn)有的數(shù)據(jù)庫(kù)或者新建的數(shù)據(jù)庫(kù)創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)對(duì)象。
②transaction:這個(gè)方法讓我們能夠控制一個(gè)事務(wù),以及基于這種情況執(zhí)行提交或者回滾。
③executeSql:這個(gè)方法用于執(zhí)行實(shí)際的 SQL 查詢。
打開數(shù)據(jù)庫(kù):
var db=openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024,fn); //openDatabase() 方法對(duì)應(yīng)的五個(gè)參數(shù)分別為:數(shù)據(jù)庫(kù)名稱、版本號(hào)、描述文本、數(shù)據(jù)庫(kù)大小、創(chuàng)建回調(diào)
執(zhí)行查詢操作:
var db=openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS WIN (id unique, name)'); });
插入數(shù)據(jù):
var db=openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS WIN (id unique, name)'); tx.executeSql('INSERT INTO WIN (id, name) VALUES (1, "winty")'); tx.executeSql('INSERT INTO WIN (id, name) VALUES (2, "LuckyWinty")'); });
讀取數(shù)據(jù):
db.transaction(function (tx) { tx.executeSql('SELECT * FROM WIN', [], function (tx, results) { var len=results.rows.length, i; msg="<p>查詢記錄條數(shù): " + len + "</p>"; document.querySelector('#status').innerHTML +=msg; for (i=0; i < len; i++){ alert(results.rows.item(i).name ); } }, null); });
由這些操作可以看出,基本上都是用SQL語(yǔ)句進(jìn)行數(shù)據(jù)庫(kù)的相關(guān)操作,如果你會(huì)MySQL的話,這個(gè)應(yīng)該比較容易用。
索引數(shù)據(jù)庫(kù) (IndexedDB) API(作為 HTML5 的一部分)對(duì)創(chuàng)建具有豐富本地存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)密集型的離線 HTML5 Web 應(yīng)用程序很有用。同時(shí)它還有助于本地緩存數(shù)據(jù),使傳統(tǒng)在線 Web 應(yīng)用程序(比如移動(dòng) Web 應(yīng)用程序)能夠更快地運(yùn)行和響應(yīng)。
異步API:
在IndexedDB大部分操作并不是我們常用的調(diào)用方法,返回結(jié)果的模式,而是請(qǐng)求——響應(yīng)的模式,比如打開數(shù)據(jù)庫(kù)的操作
這樣,我們打開數(shù)據(jù)庫(kù)的時(shí)候,實(shí)質(zhì)上返回了一個(gè)DB對(duì)象,而這個(gè)對(duì)象就在result中。由上圖可以看出,除了result之外。還有幾個(gè)重要的屬性就是onerror、onsuccess、onupgradeneeded(我們請(qǐng)求打開的數(shù)據(jù)庫(kù)的版本號(hào)和已經(jīng)存在的數(shù)據(jù)庫(kù)版本號(hào)不一致的時(shí)候調(diào)用)。這就類似于我們的ajax請(qǐng)求那樣。我們發(fā)起了這個(gè)請(qǐng)求之后并不能確定它什么時(shí)候才請(qǐng)求成功,所以需要在回調(diào)中處理一些邏輯。
關(guān)閉與刪除:
function closeDB(db){ db.close(); } function deleteDB(name){ indexedDB.deleteDatabase(name); }
數(shù)據(jù)存儲(chǔ):
indexedDB中沒有表的概念,而是objectStore,一個(gè)數(shù)據(jù)庫(kù)中可以包含多個(gè)objectStore,objectStore是一個(gè)靈活的數(shù)據(jù)結(jié)構(gòu),可以存放多種類型數(shù)據(jù)。也就是說一個(gè)objectStore相當(dāng)于一張表,里面存儲(chǔ)的每條數(shù)據(jù)和一個(gè)鍵相關(guān)聯(lián)。
我們可以使用每條記錄中的某個(gè)指定字段作為鍵值(keyPath),也可以使用自動(dòng)生成的遞增數(shù)字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)也有差異。
天下數(shù)據(jù)是國(guó)內(nèi)屈指可數(shù)的擁有多處海外自建機(jī)房的新型IDC服務(wù)商,被業(yè)界公認(rèn)為“中國(guó)IDC行業(yè)首選品牌”。
天下數(shù)據(jù)與全球近120多個(gè)國(guó)家頂級(jí)機(jī)房直接合作,提供包括香港、美國(guó)、韓國(guó)、日本、臺(tái)灣、新加坡、荷蘭、法國(guó)、英國(guó)、德國(guó)、埃及、南非、巴西、印度、越南等國(guó)家和地區(qū)的服務(wù)器、云服務(wù)器的租用服務(wù),需要的請(qǐng)聯(lián)系天下數(shù)據(jù)客服!
除提供傳統(tǒng)的IDC產(chǎn)品外,天下數(shù)據(jù)的主要職責(zé)是為大中型企業(yè)提供更精細(xì)、安全、滿足個(gè)性需求的定制化服務(wù)器解決方案,特別是在直銷、金融、視頻、流媒體、游戲、電子商務(wù)、區(qū)塊鏈、快消、物聯(lián)網(wǎng)、大數(shù)據(jù)等諸多行業(yè),為廣大客戶解決服務(wù)器租用中遇到的各種問題。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。