chrome插件开发入门-保姆级攻略
文章目錄
- 這里先插播一條消息
- chrome插件應該包含哪些文件及文件夾
- 重要配置說明
- 開始手擼一個插件
- 準備工作
- 創建一個文件夾,如我的叫 extensions (之后說的根目錄都是指這個目錄下)
- 文件夾下創建一個 img 目錄,用于存放一些logo之類的圖片
- 文件夾下創建一個 html 目錄,用于存放html文件
- 文件夾下創建一個 js 目錄,用于存放js文件
- 文件夾下創建一個 css 目錄,用于存放css文件
- 文件夾根目錄下創建一個 manifest.json 文件
- pupup部分
- background部分
- content部分
- 去廣告插件
- 頁面跳轉和cookie
- 過程中問題記錄
- 代碼地址
這里先插播一條消息
Manifest version 2 is deprecated, and support will be removed in 2023. See https://developer.chrome.com/blog/mv2-transition/ for more details.
MV2版本的chrome插件在2023年停止支持
chrome插件應該包含哪些文件及文件夾
D:. │ manifest.json │ ├─html │ index.html │ ├─images │ icon-128.png │ icon-16.png │ ├─scripts │ background.js │ ├─styles │ main.css │ └─_locales├─en│ messages.json│└─zh_CNmessages.json分析
重要配置說明
manifest.json
額外的配置參見https://blog.csdn.net/sysuzjz/article/details/51648163
{"manifest_version": 3, // 清單版本號,建議使用 版本 3,版本 1和2 是舊的,已棄用,不建議使用"name": "first-test-plugin", // 插件名稱"version": "0.0.1", // 插件版本"description": "這里是第一個測試插件", // 描述,可寫可不寫"icons":{"16": "images/custom/16x16.png","48": "images/custom/48x48.png","128": "images/custom/128x128.png"},// !!!browser_action和page_action只能添加一個"browser_action": //瀏覽器級別行為,所有頁面均生效{"default_icon": "images/custom/16x16.png", // 圖標的圖片"default_title": "Hello lanfengqiuqian", // 鼠標移到圖標顯示的文字"default_popup": "html/popup.html" // 單擊圖標后彈窗頁面},"page_action": //頁面級別的行為,只在特定頁面下生效{"default_icon":{"24": "images/custom/24x24.png","38": "images/custom/38x38.png"},"default_popup": "html/popup.html","default_title": "Hello lanfengqiuqian"},"author": "lanfengqiuqian", // 可選填寫"automation": false, // 是否開啟自動化"background": // 背景頁的腳本路徑,一般為插件目錄的相對地址{"scripts": ["scripts/background.js","scripts/devtools-page.js"]},"devtools_page": "html/devtools-page.html", // 在開發工具中的頁面"content_scripts": [ // 內容腳本一般植入會被植入到頁面中, 并且可以控制頁面中的dom{"js": ["js/else-insert.js"], // 這里面的數組都是可以放多個的"css": ["css/else-insert.css"],"matches": ["<all_urls>"] // 被植入到頁面,只在這些站點下 content_scripts會運行}],"permissions": [ // 安裝的時候提示?的權限"cookies", // 使用cookies"webRequest", // 使用web請求"http://*", // 可以通過executeScript或者insertCSS訪問的網站地址。如: https://*.google.com/"management", //"storage", // 使用本地存儲"tabs", // 操作標簽"contextMenus" //右鍵菜單]"default_locale ": "zh_CN" //默認語言(比如"zh_CN") }開始手擼一個插件
準備工作
創建一個文件夾,如我的叫 extensions (之后說的根目錄都是指這個目錄下)
文件夾下創建一個 img 目錄,用于存放一些logo之類的圖片
放入一張圖片,如logo.png
文件夾下創建一個 html 目錄,用于存放html文件
文件夾下創建一個 js 目錄,用于存放js文件
這里如果你想先放一個jquery文件用于加載也是可以的,我后面為了方便使用的是script引入
文件夾下創建一個 css 目錄,用于存放css文件
文件夾根目錄下創建一個 manifest.json 文件
{"manifest_version":3,"name":"這是插件名稱","version":"0.0.1","description":"這是插件描述","action":{"default_title":"這是鼠標移上去時提示文字","default_popup":"html/popup.html"},"icons":{"16":"img/logo.png","32":"img/logo.png","48":"img/logo.png","128":"img/logo.png"} }然后chrome擴展程序【加載已解壓的擴展程序】選擇剛才創建的extensions目錄
效果如下
pupup部分
在/html新建一個popup.html文件,然后在manifest.json中的action配置popup的路徑
"action":{"default_title":"這是鼠標移上去時提示文字","default_popup":"html/popup.html" } <!DOCTYPE html> <html> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><link rel="stylesheet" type="text/css" href="../css/popup.css" /> </head> <body><div class="btn">測試<input id="TEST" class="checkbtn" type="checkbox" /></div> </body> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="../js/popup.js"></script> </html>在css和js目錄中分別新建popup.css和popup.js文件
/* popup.css */ .btn{width: 100px;height: 30px;font-size: large; } //popup.js $(".checkbtn").click(function(){alert($(this).attr('id')); });然后重載擴展程序
點擊插件,效果如下
待解決問題
每次勾選的checkbox都會被還原,所以接下來需要做一個本地存儲來保存popup的改變
background部分
在manifest.json中加入service_worker的配置路徑和permissions
"background":{"service_worker":"background.js" }, "permissions":["storage"]注意:service_worker說明
在根目錄寫background.js文件
//background.js chrome.runtime.onInstalled.addListener(() => {DBdata("clear");//清除插件保存的本地數據 }); //插件用的數據都存儲在storage.local中 function DBdata(mode,callback,data){//操作本地存儲的函數if(mode=="set"){//保存本地數據console.log('set-LocalDB');chrome.storage.local.set({LocalDB: data});}else if(mode=="get"){//獲取chrome.storage.local.get('LocalDB', function(response) {typeof callback == 'function' ? callback(response) : null;});}else if(mode=="clear"){//清空chrome.storage.local.clear();} }打開popup.js,把原來的點擊事件刪掉,在其中加入初始化和連接service_worker的腳本
//popup.js window.bgCommunicationPort = chrome.runtime.connect();//初始化bgCommunicationPort $(".checkbtn").click(function(){bgCommunicationPort.postMessage({//發送到bg,鍵值可以自由設置Direct : $(this).attr('id'),//目標Content : '測試內容',//內容step : 0//步驟}); }); $(document).ready(function(){//打開popup時觸發,讀取之前存儲的參數bgCommunicationPort.postMessage({fromPopup:'getDB'});//向background發送消息bgCommunicationPort.onMessage.addListener(function(receivedPortMsg) {//監聽backgroundconsole.log(receivedPortMsg);//這是background發來的內容if(receivedPortMsg&&receivedPortMsg.Direct){$(".checkbtn").prop({'checked': false});//初始化按鈕$("#"+receivedPortMsg.Direct).prop({'checked': true});}}); });打開background.js,在其中加入監聽popup的腳本(這里不要刪除原來的哦,加到后面即可)
//background.js chrome.runtime.onConnect.addListener(function(port) {//接收到popupport.onMessage.addListener(function(receivedMsg) {//監聽popup發來的內容receivedMsgif(receivedMsg.fromPopup&&receivedMsg.fromPopup=='getDB'){//如果接收到了getDB,這里讀取數據并返回相當于初始化popup頁面DBdata('get',function(res){port.postMessage(res.LocalDB);//發送到popup});}else{//如果不是,則說明是收到來自popup手動點擊設置的數據,存入以用于popup打開時展示DBdata('set','',receivedMsg)}}) });重載插件
這個時候會發現有兩個報錯
發現是用script引入的jquery報跨域
那么就改為文件引入唄
在js目錄下新建jquery.js
到https://jquery.com/download/去下載production版本的js
然后把他的內容放到jquery.js中
修改popup.html文件中的jquery引入
<script src="../js/jquery.js"></script>重載插件,發現報錯都好了
測試
每次重置勾選的問題已經好了
content部分
content可以注入到瀏覽的網頁,操作dom,所以就可以實現很多功能了
注意這里現在只是匹配的localhost哦
新建js/content.js,在content.js中寫入
//content.js manifest匹配地址的頁面在刷新時會直接執行這里的代碼 chrome.runtime.sendMessage(chrome.runtime.id, {//當頁面刷新時發送到bgfromContent: 'getDB' });chrome.runtime.onMessage.addListener(function(senderRequest, sender, sendResponse) {//接收到bgconsole.log('demo已運行');var LocalDB=senderRequest.LocalDB;console.log(LocalDB);switch(LocalDB.Direct){case 'TEST':console.log(123123);break;default:break;}// 不寫會報錯 Unchecked runtime.lastError: The message port closed before a response was received.sendResponse('這里是content返回值'); });然后background.js中加入監聽content的代碼
//background.js chrome.runtime.onMessage.addListener(function (senderRequest, sender, sendResponse) {//接收到content// 不寫會報錯 Unchecked runtime.lastError: The message port closed before a response was received.sendResponse({ msg: '接收到content' });console.log(senderRequest);if (senderRequest.fromContent && senderRequest.fromContent == 'getDB') {//接收到fromContent:getDBDBdata('get', function (res) {//從本地取數據if (res.LocalDB) {var LocalDB = res.LocalDB;switch (LocalDB.Direct) {//如果是存入的TEST按鈕case 'TEST':chrome.tabs.query({active: true,currentWindow: true}, function (tabs) {chrome.tabs.sendMessage(tabs[0].id, { LocalDB: LocalDB }, function (res) {console.log('接收content的回調', res);});//發送到content });break;default:break;}}});} });這里注意sendResponse這個方法,有的沒有在回調中加上這個參數,導致找不到
重載插件
代碼執行順序
插件初始化階段
手動點擊插件圖標,勾選插件
網頁刷新階段
去廣告插件
說明:這里對于廣告的判斷是類名為 .ad 的元素
如我的vue頁面
<div><h2 class="ad">第一條廣告</h2><h2 class="ad">第二條廣告</h2><h2 class="ad">第三條廣告</h2><h2>這里是正常的數據</h2> </div>在popup.html中增加一個去廣告按鈕
<div class="btn">去廣告<input id="removeAD" class="checkbtn" type="checkbox" /> </div>在background.js中監聽content部分增加對于removeAD的判斷
//如果是存入的removeAD按鈕 case 'removeAD':chrome.tabs.query({active: true, currentWindow: true}, function(tabs){chrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB});//發送到content });break;在content.js中監聽background.js部分增加removeAD的判斷
case 'removeAD'://隱藏含有ad的元素,來達到去廣告的效果$(".ad").hide();break;重載插件,勾選頁面中的去廣告,然后刷新頁面,發現廣告已經沒有了
頁面跳轉和cookie
和popup一樣,content關閉之后也不會保存數據,當我們在A頁面獲取數據之后想要放到B頁面上去,在content直接跳轉是不會把獲取到的數據傳過去的,所以和background鏈接保存本地數據就派上用場了
案例:將csdn的cookie的UserNick顯示在localhost:8081中
在manifest.json中配置【域名腳本匹配】、【權限】和【主機權限】
"permissions":["storage", "cookies"], "host_permissions": ["*://www.csdn.net/*" ], "content_scripts":[{"js":["js/jquery.js","js/content.js"],"matches":["*://localhost/*", "*://www.csdn.net/*"],"run_at":"document_end" }]這里千萬要注意的是一定要能夠匹配上的url,否則可能引起頁面腳本無反應或者獲取不到cookie
在popup.html中增加按鈕
<div class="btn">csdn<input id="checkCsdnUserNick" class="checkbtn" type="checkbox" /> </div>在background.js中增加對于csdn按鈕的判斷
case 'checkCsdnUserNick':console.log('LocalDB', LocalDB)//popup設置數據的時候有個step屬性,在多步操作的時候就開始發揮作用了if(LocalDB.step==0){LocalDB.step = 1;//將step設置成1chrome.storage.local.set({LocalDB: LocalDB//保存到本地數據},function() {chrome.tabs.update(null, {//將前臺頁面跳轉到設置的url// 這里的url不用帶斜杠 /url: 'https://www.csdn.net'});});}else if(LocalDB.step==1){//因為csdn的地址我們也匹配了所以content在跳轉到csdn之后會還是會回來,不同的是step已經是1了chrome.cookies.get({//獲取cookie'url': "https://www.csdn.net",'name': 'UserNick'}, function(cookie) {console.log('cookie', cookie);console.log(cookie.value);//獲取到的值LocalDB.cookie=cookie.value;//把獲取到的值放到本地數據的cookie屬性里LocalDB.step = 2;//將step設置成2chrome.storage.local.set({//獲取到cookie之后跳轉到第二個頁面LocalDB: LocalDB//保存到本地數據},function() {chrome.tabs.update(null, {//將前臺頁面跳轉到設置的urlurl: 'http://localhost:8081/'});});});}else if(LocalDB.step==2){//第二步chrome.tabs.query({active: true, currentWindow: true}, function(tabs){//發送到contentchrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB}); });}break;在content.js中增加對于csdn按鈕的判斷
case 'checkCsdnUserNick':if(LocalDB.step==2){$("body").append('<h1>'+LocalDB.cookie+'</h1>');}break;重載插件,到csdn.net中開啟插件,勾選csdn,然后刷新頁面就能看到效果
會獲取csdn.net中cookie中的昵稱,然后跳轉到localhost:8081,進行顯示
過程中問題記錄
Unchecked runtime.lastError: The message port closed before a response was received.
這個問題通常是由于其他插件引起的,注意排查,找到受影響的插件禁用即可
大多數人是由于【迅雷】插件或者【油猴】插件引起的
擴展【移除】旁邊多了一個【錯誤】的按鈕
如果有錯誤提示,根據提示排查即可
如果沒有錯誤提示,嘗試將擴展移除重新加載即可
檢查是否沒有把sendMessage和sendResponse配套使用
每一個sendMessage都需要和sendResponse進行呼應
也就是說,在每一個chrome.runtime.onMessage.addListener的回調函數中,需要使用sendResponse進行返回
可以參見https://blog.csdn.net/m0_37729058/article/details/89186257
service worker看不到content.js的console.log
原因是因為這個js是嵌入到頁面中的,所以需要在使用的網頁的控制臺查看,而不是service worker
無法獲取到cookie
可能原因如下
沒有授權host_permissions,控制臺會報錯Unchecked runtime.lastError: No host permissions for cookies at url: "https://www.csdn.net/".
檢查manifest.json中的此項配置,沒有添加或者沒有匹配上都會造成這個問題
檢查chrome.cookies.get這個方法中的url是否完全正確
代碼地址
github跳轉
總結
以上是生活随笔為你收集整理的chrome插件开发入门-保姆级攻略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 执行yum:Error: Cannot
- 下一篇: 从头学习linux C 冒泡法排序