編寫第一個chrome外掛?
編寫chrome外掛完全就是前端知識加上一些專門的知識。
假設pj1
資料夾下有檔案index.html
<!DOCTYPE html>
<html>
<head>
<title>Hi</title>
<meta charset="utf-8"/>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="main">
hello,world
</div>
<script type="text/javascript">
setTimeout(()=>{
document.getElementById("main").innerText = "hi,saltfish"
},1000)
</script>
</body>
</html>
複製程式碼
嗯,現在看來他只是普通的html,其實,你只要在當前資料夾下加上manifest.json
檔案,chrome瀏覽器就可以把它識別為外掛,成為瀏覽器右上角的小圖示。
如何什麼是manifest.json
,如何編寫?
manifest 是貨單的意思,這個檔案就是chrome規定的的外掛配置檔案的名稱
{
"name": "My Extension",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_popup": "index.html"
}
}
複製程式碼
name、version不用解釋,manifest_version
類似與XML的schema檔案,用來約束manifest_version
自身的格式,目前,它的值永遠是2。
而default_popup
作用:當使用者點選外掛的小圖示後,顯示的畫面,就是把它所引用的HTML渲染後得到的。
如何釋出?
在chrome瀏覽器訪問 chrome://extensions/ 就會看到
點選LOAD UNPACKED
再選取存放檔案的資料夾即可。你會立刻在瀏覽器又上角看到自己的外掛。
點選後會顯示index.html對應的內容
為了統一規範,我們可以把index.html改名為popup.html,同時記得修改"default_popup"的值
關於popup.html
我們可以看到,chrome外掛的UI是用HTML編寫的(相應的指令碼也是js寫得),所以chrome外掛對我們前端開發者來說非常好學。
每當我們點選小圖示時,chrome就會讀取配置檔案中定義的HTML檔案。
在chrome外掛的UI中,沒有title
等的概念,所以我們可以吧一些沒用的標籤給刪除掉。
css檔案和一般前端一模一樣
在`style.css``新增
body{
width: 300px;
height: 300px;
background-color: antiquewhite;
}
複製程式碼
(記得在popup.html中引用哦) 在重新整理外掛,可以看到
js指令碼
細心的同學可能注意到,在之前的popup.html中明明有指令碼
<script type="text/javascript">
setTimeout(()=>{
document.getElementById("main").innerText = "hi,saltfish"
},1000)
</script>
複製程式碼
為什麼頁面一直不重新整理?
因為chrome官方規定js指令碼只能引入,不能嵌入HTML(我也不知道為什麼這樣規定)
新增標籤<script src="script.js"></script>
並將指令碼移動到對應位置,再重新整理外掛,你就可以看到正確的結果了。
這裡的js指令碼和一般的js環境相同,不過console.log 不能用,因為chrome也不知往哪裡列印結果,不過你可以使用alert函式來除錯程式碼。
popup.html的生命週期
該檔案在使用者點選小圖示後載入,和你開啟一般的網頁一模一樣,只不過對應的UI顯示在瀏覽器的右上角,每當你點選其他地方chrome就會關閉這個視窗,對應的js環境也會被銷燬,也就是說,你每次點選小圖示,就會重新渲染HTML和css,並重新執行js程式碼。
正是因為這個特性,popup.html以及他引入的js指令碼,只處理UI相關。一些業務邏輯放在其他地方,下面來介紹
確認下目錄結構
$ tree
.
├── manifest.json
├── popup.html
├── script.js
└── style.css
複製程式碼
$ cat manifest.json
{
"name": "My Extension",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_popup": "popup.html"
}
}
複製程式碼
background.js
將manifest.json修改為:
{
"name": "My Extension",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_icon": {
"19": "images/icon19.png"
},
"default_popup": "popup.html"
},
"background": {
"scripts": [
"background/bg.js"
]
}
}
複製程式碼
並新增background/bg.js
檔案,
background
欄位定義的js程式碼在開啟瀏覽器時執行,知道瀏覽器關閉。
setInterval(()=>{
alert((new Date()).toDateString())
},2000)
複製程式碼
在bg.js新增上述程式碼,發現瀏覽器一經載入,就不停彈出對話方塊,不管是否點選了小圖示,不管你做了什麼操作,他都是一直執行。
現在註釋上述程式碼
content_scripts
有時候我們的外掛希望做到:
當使用者開啟某個網頁後,再進行操作。比如使用者開啟github.com後,彈出“hi,it is github”。如何實現呢
再manifest.json
新增:
"content_scripts": [
{
"matches": ["*://github.com/*"],
"js": ["content/github.com.js"]
}
]
複製程式碼
並新增相應檔案,在js程式碼中寫上
alert("hi,it is github")
複製程式碼
content_script是個陣列,定義了一些url與script的聯絡,噹噹使用者訪問相應的網址的時候,chrome會等待頁面載入完成後,執行相應的js程式碼。
content_script可以訪問當前頁面的dom和localstorage,但是無法訪問當前頁面的js變數
content_script在每次載入相匹配的頁面後執行,頁面被重新整理後對應的content_script也會被重行執行。
三種js環境
我們看到,我們之前提及了三種js環境、background.js,content_script,popup.html引用的,現在來捋一捋他們的關係和區別
內容 | background.js | content_script | popup.js |
---|---|---|---|
生命週期 | 瀏覽器載入後一直執行 | 開啟相應url後執行 | 每次點選圖示後執行 |
dom | 沒有能操作的dom | 能讀取當前頁面dom | popup.html的dom |
js變數 | 如果有多個bg.js,並列指令碼間不共享js變數 | 與原生頁面的js變數隔絕,如果多個content_script匹配到同一個url,他們的一直執行,js變數依舊隔絕 | |
localstorage | 每一個外掛對應一個localstorage,被不同的bg.js共享 | 和當前url的localstorage共享 | 和當前外掛共享(這是bg.js和popup.js一種通訊方式) |
這幾點是我自己在學習中,不斷測試,得到這幾點結論(測試過程就不寫了,很容易想到)。
確認下目錄
$ tree
.
├── background
│ └── bg.js
├── content
│ └── github.com.js
├── manifest.json
├── popup.html
├── script.js
└── style.css
複製程式碼
頁面間通訊
之前,說過,各中js程式碼中的變數是不共享的,那麼我們如何讓他們通訊呢? 比如,當使用者訪問github.com時,讓content_script向bg.js 說一聲hello? chrome設計了一個介面api: 在github.com.js:
let message = "hello"
chrome.runtime.sendMessage(message, function(response){
console.log(response)
});
複製程式碼
bg.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
alert(message)
sendResponse({content:"hi,it is bg.js"})
});
複製程式碼
重新整理外掛並開啟github,發現彈出“hello",對應github頁面控制檯也列印出{content:"hi,it is bg.js"}
可以看到:整個過程類似於HTTP請求,content_script發起一個請求,bg.js回應。 而且執行直接傳遞js變數
結語
好了這幾點是前置知識,下一篇文章來改造一個前端專案。