chrome 擴展是用傳統的 HTML、CSS、JS、圖片等靜態資源開發並最終打包成後綴爲 .crx
的一個壓縮包。因此,它和咱們日常開發的頁面沒有多大的區別,因此若是你想引入前端開發所用的各類框架,組件庫,構建工具也都是能夠的。主要區別只有 2 個:javascript
擴展的安裝方式有 3 種:css
.crx
壓縮包,把壓縮包直接拖拽到 chrome 的擴展管理頁面這裏只簡單地介紹幾種常常見到的,還有更多的展示形式,你們感興趣能夠去官方文檔詳細瞭解html
Octotree
(對 gitub 項目頁面作導航)vue-devtool
等框架提供的調試工具具體擴展各個組成部分的學習,咱們以一個很簡單的例子爲基礎進行介紹,這個擴展是一個爲頁面添加回到頂部功能的擴展。前端
每個擴展都必需要有的一個名字爲 manifest.json 的配置文件,這個文件聲明瞭此擴展用到了哪些功能,及各個功能須要用到的靜態資源vue
這個 backToTop 擴展的配置已經在途中說明,已經有了基本的說明,下面對一些配置項作下額外的說明,所有配置能夠在官網查看:java
chrome.pageAction
API 來動態的設置擴展在某些頁面的行爲這部分咱們說下擴展開發核心的幾種 JSgit
popup 頁面生命週期是點擊彈出時,初始化,關閉時,頁面也跟着銷燬, 而且這個頁面沒有任何跨域的限制。它在咱們擴展裏的做用是配置頁面裏 backToTop icon 的樣式,並存入storage。web
chrome.storage.local.get(['right', 'bottom', 'icon'], function(result) {
if(result) {
// 初始化
right.value = result.right || '';
bottom.value = result.bottom || '';
if(result.icon) {
img.src = result.icon;
img.dataset.uploaded = true;
}
}
})
複製代碼
頁面初始化時,從 storage 取出存儲的值,初始化頁面。 保存參數時,再將相關參數存入 storagechrome
chrome.storage.local.set({right: rightVal, bottom: bottomVal});
if(img.dataset.uploaded) {
chrome.storage.local.set({icon: img.src});
}
複製代碼
注: storage API 有 2 種 storage.sync
和 storage.local
他們的區別json
localstorage
是同樣的 5M. 而 sync 存儲的大小隻有 100K 並且對於單個 key 的值大小,以及寫入的頻率也有限制,畢竟要同步服務端,因此若是開發的擴展只是用於我的使用的效率提高,不打算髮布,能夠直接用 local 就行了content-script
是咱們用來定製化頁面,實現頁面內擴展邏輯的地方。它的特色是:
content-script
建立一個 script 標籤插入到 DOM 裏 這個新的 script 裏的函數是能夠綁定的content-script
會在每個 tab 頁面裏都有一份代碼在運行content-script
纔會開始運行。那咱們的 backToTop 裏 content-script
都幹了什麼呢 首先,初始化咱們頁面裏的 icon 並根據頁面 scrollTop
判斷當前是否須要展現 icon
const el = document.createElement('div');
el.show = true; // 控制icon是否顯示
el.classList.add('ce-btt-container');
el.style.opacity = target.scrollTop > visibleHeight ? 1 : 0;
const img = document.createElement('img');
img.classList.add('ce-btt-icon');
el.appendChild(img);
chrome.storage.local.get(['right', 'bottom', 'icon'], function(result) {
el.style.right = result && result.right ? result.right + 'px' : right;
el.style.bottom = result && result.bottom ? result.bottom + 'px' : bottom;
img.src = result && result.icon ? result.icon : chrome.runtime.getURL('icons/backToTop.png');
document.body.appendChild(el);
});
複製代碼
第二步, 要想實現返回頂部,固然要給咱們的 icon 綁定點擊事件,以及監聽 scroll
事件判斷何時該隱藏展現
el.addEventListener('click', function(e) {
let step = 20;
let timer = setInterval(() => {
if(target.scrollTop <= 0) {
clearInterval(timer);
} else {
step += 20;
target.scrollTop -= step;
}
}, 20);
});
const handleScroll = function() {
if(!el.show) return false; // icon不顯示時,不處理
if(target.scrollTop > visibleHeight) {
el.style.opacity = 1;
} else {
el.style.opacity = 0;
}
};
container.addEventListener('scroll', throttle(handleScroll, 300));
複製代碼
第三步, 若是 popup 頁面有配置的變動, content-script
都須要馬上進行更新
chrome.storage.onChanged.addListener(function(changes, namespace) {
if(changes.bottom) {
el.style.bottom = `${changes.bottom.newValue}px`;
}
if (changes.right) {
el.style.right = `${changes.right.newValue}px`;
}
if (changes.icon) {
img.src = changes.icon.newValue;
}
});
複製代碼
注: 這裏須要注意的是,由於咱們要把擴展裏的 icon 插入到頁面,因此須要在 manifest.json
裏配置 web_accessible_resources
賦予頁面能夠訪問咱們指定的擴展靜態資源的權限。這是由於頁面裏 icon 的 src 屬性是這樣的
background
能夠理解爲是擴展在後臺一直運行的一個 JS(實際並非), 它在整個瀏覽器裏只會有一個 js 在運行。在 background 的配置裏,有一個 persistent
的配置, 當它爲 true 時,background 纔會一直運行,false 時,瀏覽器會檢測長時間不活動時,自動卸載調,只有監聽的事件發生時,纔會從新執行,官方的說明是
The only occasion to keep a background script persistently active is if the extension uses chrome.webRequest API to block or modify network requests. The webRequest API is incompatible with non-persistent background pages.
因此絕大多數時候,咱們把它設爲 false 就能夠了。另外 background
也是能夠跨域的, 因此咱們能夠總結出,除了頁面內的 js chrome 對其餘的 js 都沒有跨域的限制。
好,咱們看看咱們擴展裏 background
幹了啥
首先,初始時,確定要監聽瀏覽器的初始化事件,才能夠綁定擴展關注的事件。
chrome.runtime.onInstalled.addEventListener(function() {
// init extention
})
複製代碼
第二步,由於有的頁面已經提供了返回頂部的功能,因此這個時候咱們須要提供能夠把咱們的 icon 永久隱藏的功能,咱們在 background
初始化的邏輯中,建立一個鼠標右鍵的菜單項,這個菜單項能夠實現 切換咱們的 icon 顯示狀態的功能
chrome.contextMenus.create({
title: 'toggle',
id: 'toggle'
});
chrome.contextMenus.onClicked.addListener(function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
sendMsg(tabs.length ? tabs[0].id : null);
});
});
function sendMsg(tabId) {
chrome.tabs.sendMessage(tabId, 'toggle', function(res) {
console.log(res);
});
}
複製代碼
發送消息這裏咱們用了 chrome.tabs
API 由於咱們每一個 tab 都會有一個 content-script
因此須要篩選出當前所在的標籤頁,而後發送消息。
最後,咱們的 content-script
須要監聽發送消息的事件,並切換 icon 的狀態
chrome.runtime.onMessage.addListener(function(req, sender, respond) {
if(req === 'toggle') {
if (target.scrollTop > visibleHeight) {
el.style.opacity = el.style.opacity === '1' ? 0 : 1;
}
el.show = !el.show;
respond('toggle success');
}
});
複製代碼
至此,整個擴展的功能就基本介紹完了,過程當中用到的 API 這裏並不做詳細的介紹,詳細使用仍是須要你們去 官網 查看
最後說一下如何調試,調試我的認爲仍是比較麻煩的, 代碼變動並無熱更新,因此須要咱們手動去擴展管理頁從新加載。並且幾種不一樣的 JS 調試的位置也不一樣,設計通信時常常須要在幾個不一樣的地方來回切換
popup
調試:在彈出的窗口裏,右鍵審查元素就能夠彈出調試窗口,調試方式和普通的頁面調試沒有區別。
background
調試: 在管理頁點擊背景頁,就能夠彈出調試窗口了
content-script
調試: 由於是在頁面運行,因此調試的地方和頁面 js 是在一個窗口裏
代碼位置:在 sources tab 下選中 Content scripts 就能夠看到頁面加載的所有的擴展 contnt-script
了。
console 輸出: 在 Console tab 下拉框裏選中要調試的擴展,就能夠看到對應擴展的 console 輸出。
在擴展管理頁,能夠打包擴展程序,打包後就能夠生成 .crx
文件
打包以後,就能夠發佈了,不過發佈須要先花 5$ 註冊開發者,我就沒有繼續下去了。
在開發過程當中,能夠發現寫一個擴展其實並不難,用到的技術都是前端天天都在用的東西。只要咱們多加留心,就會發現使用 chrome 過程當中有許多能夠提效,優化體驗的地方,這時候咱們就能夠試着用擴展的方式解決。整體來講,chrome 擴展是一種技術成本很低,就能夠幹些有趣的事情的技術
參考資料: