知識點:
- storage
- onChanged()
Chrome 為擴展應(yīng)用提供了存儲 API渴语,以便將擴展中需要保存的數(shù)據(jù)寫入本地磁盤觅赊。Chrome 提供的存儲 API 可以說是對 localStorage
的改進相满,它與 localStorage
相比有以下區(qū)別:
用戶數(shù)據(jù)可以通過 Chrome 瀏覽器的同步功能自動同步(使用
storage.sync
)content_scripts
可以直接讀取數(shù)據(jù)抠藕,而不必通過background
頁面在隱身模式下仍然可以讀出之前存儲的數(shù)據(jù)
讀寫速度更快
用戶數(shù)據(jù)可以以對象的類型保存(
localStorage
API 以字符串方式存儲數(shù)據(jù))墩朦。
對于第二點要進一步說明一下。首先 localStorage
是基于域名的绊谭。而 content_scripts
是注入到用戶當(dāng)前瀏覽頁面中的政恍,如果 content_scripts
直接讀取 localStorage
,所讀取到的數(shù)據(jù)是用戶當(dāng)前瀏覽頁面所在域中的龙誊。
所以通常的解決辦法是 content_scripts
通過 runtime.sendMessage
和 background
通信抚垃,由 background
讀寫擴展所在域(通常是 chrome-extension://extension-id/
)的 localStorage
,然后再傳遞給 content_scripts
趟大。
使用 Chrome 存儲 API 必須要在 Manifest 的 permissions
中聲明 "storage"
,之后才有權(quán)限調(diào)用铣焊。
Chrome 存儲 API 提供了 2 種儲存區(qū)域逊朽,分別是 sync
和 local
。兩種儲存區(qū)域的區(qū)別在于曲伊,sync
儲存的區(qū)域會根據(jù)用戶當(dāng)前在 Chrome
上登陸的 Google 賬戶自動同步數(shù)據(jù)叽讳,當(dāng)無可用網(wǎng)絡(luò)連接可用時,sync
區(qū)域?qū)?shù)據(jù)的讀寫和 local
區(qū)域?qū)?shù)據(jù)的讀寫行為一致坟募。
對于每種儲存區(qū)域岛蚤,Chrome 又提供了 5 個方法,分別是 get
懈糯、getBytesInUse
涤妒、set
、remove
和 clear
赚哗。
在 sync
區(qū)域存儲和讀取數(shù)據(jù):
chrome.storage.sync.set({key: value}, function() {
console.log('Value is set to ' + value);
});
chrome.storage.sync.get(['key'], function(result) {
console.log('Value currently is ' + result.key);
});
local
區(qū)域:
chrome.storage.local.set({key: value}, function() {
console.log('Value is set to ' + value);
});
chrome.storage.local.get(['key'], function(result) {
console.log('Value currently is ' + result.key);
});
下面我們寫個小例子來說明她紫。
編寫 manifest.json
文件:
{
"manifest_version": 2,
"name": "存儲測試",
"version": "1.0",
"description": "存儲測試",
"browser_action": {
"default_popup": "popup.html"
},
// 設(shè)定使用存儲的權(quán)限
"permissions": [
"storage"
]
}
編寫 popup.html
頁面:
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
width: 250px;
height: 300px;
}
</style>
<script type="text/javascript" src="js/popup.js"></script>
編寫 popup.js
文件:
var user1 = {'name': 'diego', 'age': 18}
// 往存儲中寫入數(shù)據(jù)
chrome.storage.sync.set({'user1': user1}, function() {
console.log('保存成功');
});
// 從存儲中讀取數(shù)據(jù)
chrome.storage.sync.get('user1', function(result) {
document.write('name: ' + result['user1'].name + '<br>' + 'age: ' + result['user1'].age );
});
現(xiàn)在我們能在頁面上看到剛存儲的數(shù)據(jù):
在 get()
方法中 keys
可以是字符串硅堆、包含多個字符串的數(shù)組或?qū)ο蟆?/p>
如果 keys
是字符串,則和 localStorage
的用法類似(見上例)贿讹;如果是數(shù)組渐逃,則相當(dāng)于一次讀取了多個數(shù)據(jù)。
var user1 = {'name': 'diego', 'age': 18}
var user2 = {'name': 'tony', 'age': 19}
// 往存儲中寫入數(shù)據(jù)
chrome.storage.sync.set({'user2': user2}, function() {
console.log('保存成功');
});
chrome.storage.sync.set({'user1': user1}, function() {
console.log('保存成功');
});
// 從存儲中讀取數(shù)據(jù)
chrome.storage.sync.get(['user1', 'user2'], function(result) {
document.write(
'name: ' + result['user1'].name + '<br>' + 'age: ' + result['user1'].age
+ '<hr>'
+ 'name: ' + result['user2'].name + '<br>' + 'age: ' + result['user2'].age
);
});
如果 keys
是對象民褂,則會先讀取以這個對象屬性名為鍵值的數(shù)據(jù)茄菊,如果這個數(shù)據(jù)不存在則返回 keys
對象的屬性值(比如 keys
為 {'name':'Billy'}
,如果 name
這個值存在赊堪,就返回 name
原有的值面殖,如果不存在就返回 'Billy'
)。
var user1 = {'name': 'diego', 'age': 18}
var default_user = {'name': 'default_user', 'age': 18}
// 往存儲中寫入數(shù)據(jù)
chrome.storage.sync.set({'user1': user1}, function() {
console.log('保存成功');
});
// 從存儲中讀取數(shù)據(jù)
chrome.storage.sync.get({'user2': default_user}, function(result) {
document.write('name: ' + result['user2'].name + '<br>' + 'age: ' + result['user2'].age );
});
因為 'user2'
這個值是不存在的雹食,所以返回的是 default_user
這個對象畜普;如果換成 'user1'
這個存在的值,則會返回 user1
這個對象群叶。
如果 keys
為一個空數(shù)組([]
)或空對象({}
)吃挑,則返回一個空列表,如果 keys
為 null
街立,則返回所有存儲的數(shù)據(jù)舶衬。
getBytesInUse()
方法為獲取一個數(shù)據(jù)或多個數(shù)據(jù)所占用的總空間,返回結(jié)果的單位是字節(jié)赎离,完整方法為:
// sync 區(qū)域
chrome.storage.sync.getBytesInUse(keys, function(bytes){
console.log(bytes);
});
// local 區(qū)域
chrome.storage.local.getBytesInUse(keys, function(bytes){
console.log(bytes);
});
此處的 keys
只能為 null
逛犹、字符串或包含多個字符串的數(shù)組。
set()
方法為寫入數(shù)據(jù)梁剔,完整方法為:
// sync 區(qū)域
chrome.storage.sync.set(items, function(){
//do something
});
// local 區(qū)域
chrome.storage.local.set(items, function(){
//do something
});
items
為對象類型虽画,形式為鍵/值對。items
的屬性值如果是字符型荣病、數(shù)字型和數(shù)組型码撰,則儲存的格式不會改變,但如果是對象型和函數(shù)型的个盆,會被儲存為 "{}"
脖岛,如果是日期型和正則型的,會被儲存為它們的字符串形式颊亮。
remove()
方法為刪除數(shù)據(jù)柴梆,完整方法為:
// sync 區(qū)域
chrome.storage.sync.remove(keys, function(){
//do something
});
// local 區(qū)域
chrome.storage.local.remove(keys, function(){
//do something
});
其中 keys
可以是字符串,也可以是包含多個字符串的數(shù)組终惑。
clear()
方法為刪除所有數(shù)據(jù)绍在,完整方法為:
// sync 區(qū)域
chrome.storage.sync.clear(function(){
//do something
});
// local 區(qū)域
chrome.storage.local.clear(function(){
//do something
});
Chrome 同時還為存儲 API 提供了一個 onChanged()
事件,當(dāng)存儲區(qū)的數(shù)據(jù)發(fā)生改變時,這個事件會被激發(fā)揣苏。
onChanged()
的完整方法為:
chrome.storage.onChanged.addListener(function(changes, areaName){
console.log('Value in '+areaName+' has been changed:');
console.log(changes);
});
callback()
會接收到兩個參數(shù)悯嗓,第一個為 changes
,第二個是 StorageArea
卸察。changes
是詞典對象脯厨,鍵為更改的屬性名稱,值包含兩個屬性坑质,分別為 oldValue
和 newValue
合武;StorageArea
為 local
或 sync
。