日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

chrome插件开发入门-保姆级攻略

發(fā)布時(shí)間:2023/12/9 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 chrome插件开发入门-保姆级攻略 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

      • 這里先插播一條消息
      • chrome插件應(yīng)該包含哪些文件及文件夾
      • 重要配置說明
      • 開始手?jǐn)]一個(gè)插件
        • 準(zhǔn)備工作
          • 創(chuàng)建一個(gè)文件夾,如我的叫 extensions (之后說的根目錄都是指這個(gè)目錄下)
          • 文件夾下創(chuàng)建一個(gè) img 目錄,用于存放一些logo之類的圖片
          • 文件夾下創(chuàng)建一個(gè) html 目錄,用于存放html文件
          • 文件夾下創(chuàng)建一個(gè) js 目錄,用于存放js文件
          • 文件夾下創(chuàng)建一個(gè) css 目錄,用于存放css文件
        • 文件夾根目錄下創(chuàng)建一個(gè) manifest.json 文件
        • pupup部分
        • background部分
        • content部分
        • 去廣告插件
        • 頁面跳轉(zhuǎn)和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插件應(yīng)該包含哪些文件及文件夾

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
  • html:存放html頁面
  • images:存放插件圖標(biāo)
  • scripts:存放js文件
  • styles:存放樣式
  • _locales:存放多語言文件
  • manifest.json:用來配置所有和插件相關(guān)的配置,作為chrome入口文件,必須放在根目錄(必須存在)
  • 分析

  • 目錄結(jié)構(gòu)像一個(gè)web網(wǎng)頁,他的本質(zhì)上就是一個(gè)網(wǎng)站類應(yīng)用,是一個(gè)webapp
  • 相對(duì)于普通的webapp,還可以調(diào)用更多的瀏覽器層面的api,包括數(shù)錢、歷史記錄、網(wǎng)絡(luò)請(qǐng)求攔截、截獲用戶輸入等等
  • 重要配置說明

    manifest.json

    額外的配置參見https://blog.csdn.net/sysuzjz/article/details/51648163

    {"manifest_version": 3, // 清單版本號(hào),建議使用 版本 3,版本 1和2 是舊的,已棄用,不建議使用"name": "first-test-plugin", // 插件名稱"version": "0.0.1", // 插件版本"description": "這里是第一個(gè)測試插件", // 描述,可寫可不寫"icons":{"16": "images/custom/16x16.png","48": "images/custom/48x48.png","128": "images/custom/128x128.png"},// !!!browser_action和page_action只能添加一個(gè)"browser_action": //瀏覽器級(jí)別行為,所有頁面均生效{"default_icon": "images/custom/16x16.png", // 圖標(biāo)的圖片"default_title": "Hello lanfengqiuqian", // 鼠標(biāo)移到圖標(biāo)顯示的文字"default_popup": "html/popup.html" // 單擊圖標(biāo)后彈窗頁面},"page_action": //頁面級(jí)別的行為,只在特定頁面下生效{"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, // 是否開啟自動(dòng)化"background": // 背景頁的腳本路徑,一般為插件目錄的相對(duì)地址{"scripts": ["scripts/background.js","scripts/devtools-page.js"]},"devtools_page": "html/devtools-page.html", // 在開發(fā)工具中的頁面"content_scripts": [ // 內(nèi)容腳本一般植入會(huì)被植入到頁面中, 并且可以控制頁面中的dom{"js": ["js/else-insert.js"], // 這里面的數(shù)組都是可以放多個(gè)的"css": ["css/else-insert.css"],"matches": ["<all_urls>"] // 被植入到頁面,只在這些站點(diǎn)下 content_scripts會(huì)運(yùn)行}],"permissions": [ // 安裝的時(shí)候提示?的權(quán)限"cookies", // 使用cookies"webRequest", // 使用web請(qǐng)求"http://*", // 可以通過executeScript或者insertCSS訪問的網(wǎng)站地址。如: https://*.google.com/"management", //"storage", // 使用本地存儲(chǔ)"tabs", // 操作標(biāo)簽"contextMenus" //右鍵菜單]"default_locale ": "zh_CN" //默認(rèn)語言(比如"zh_CN") }

    開始手?jǐn)]一個(gè)插件

    準(zhǔn)備工作

    創(chuàng)建一個(gè)文件夾,如我的叫 extensions (之后說的根目錄都是指這個(gè)目錄下)
    文件夾下創(chuàng)建一個(gè) img 目錄,用于存放一些logo之類的圖片

    放入一張圖片,如logo.png

    文件夾下創(chuàng)建一個(gè) html 目錄,用于存放html文件
    文件夾下創(chuàng)建一個(gè) js 目錄,用于存放js文件

    這里如果你想先放一個(gè)jquery文件用于加載也是可以的,我后面為了方便使用的是script引入

    文件夾下創(chuàng)建一個(gè) css 目錄,用于存放css文件

    文件夾根目錄下創(chuàng)建一個(gè) manifest.json 文件

    {"manifest_version":3,"name":"這是插件名稱","version":"0.0.1","description":"這是插件描述","action":{"default_title":"這是鼠標(biāo)移上去時(shí)提示文字","default_popup":"html/popup.html"},"icons":{"16":"img/logo.png","32":"img/logo.png","48":"img/logo.png","128":"img/logo.png"} }

    然后chrome擴(kuò)展程序【加載已解壓的擴(kuò)展程序】選擇剛才創(chuàng)建的extensions目錄

    效果如下

    pupup部分

  • 在/html新建一個(gè)popup.html文件,然后在manifest.json中的action配置popup的路徑

    "action":{"default_title":"這是鼠標(biāo)移上去時(shí)提示文字","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')); });
  • 然后重載擴(kuò)展程序

    點(diǎn)擊插件,效果如下

  • 待解決問題

    每次勾選的checkbox都會(huì)被還原,所以接下來需要做一個(gè)本地存儲(chǔ)來保存popup的改變

  • background部分

  • 在manifest.json中加入service_worker的配置路徑和permissions

    "background":{"service_worker":"background.js" }, "permissions":["storage"]

    注意:service_worker說明

  • 這個(gè)是一直伴隨插件運(yùn)行的后臺(tái)腳本
  • 沒有前端頁面,不支持dom,所以不能引入jQuery和其他js
  • 所有需要保持運(yùn)行的腳本都需要直接卸載background.js文件里
  • 同樣也不支持XMLHttpRequest,所以需要使用fetch來替代xhr請(qǐng)求
  • 一定要放在根目錄(擴(kuò)展文件根目錄,不是電腦磁盤根目錄),否則在使用的時(shí)候會(huì)出現(xiàn)service worker(無效)提示
  • 可以在擴(kuò)展程序=>查看視圖點(diǎn)擊彈出的控制臺(tái)查看輸出
  • 在根目錄寫background.js文件

    //background.js chrome.runtime.onInstalled.addListener(() => {DBdata("clear");//清除插件保存的本地?cái)?shù)據(jù) }); //插件用的數(shù)據(jù)都存儲(chǔ)在storage.local中 function DBdata(mode,callback,data){//操作本地存儲(chǔ)的函數(shù)if(mode=="set"){//保存本地?cái)?shù)據(jù)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,把原來的點(diǎn)擊事件刪掉,在其中加入初始化和連接service_worker的腳本

    //popup.js window.bgCommunicationPort = chrome.runtime.connect();//初始化bgCommunicationPort $(".checkbtn").click(function(){bgCommunicationPort.postMessage({//發(fā)送到bg,鍵值可以自由設(shè)置Direct : $(this).attr('id'),//目標(biāo)Content : '測試內(nèi)容',//內(nèi)容step : 0//步驟}); }); $(document).ready(function(){//打開popup時(shí)觸發(fā),讀取之前存儲(chǔ)的參數(shù)bgCommunicationPort.postMessage({fromPopup:'getDB'});//向background發(fā)送消息bgCommunicationPort.onMessage.addListener(function(receivedPortMsg) {//監(jiān)聽backgroundconsole.log(receivedPortMsg);//這是background發(fā)來的內(nèi)容if(receivedPortMsg&&receivedPortMsg.Direct){$(".checkbtn").prop({'checked': false});//初始化按鈕$("#"+receivedPortMsg.Direct).prop({'checked': true});}}); });
  • 打開background.js,在其中加入監(jiān)聽popup的腳本(這里不要?jiǎng)h除原來的哦,加到后面即可)

    //background.js chrome.runtime.onConnect.addListener(function(port) {//接收到popupport.onMessage.addListener(function(receivedMsg) {//監(jiān)聽popup發(fā)來的內(nèi)容receivedMsgif(receivedMsg.fromPopup&&receivedMsg.fromPopup=='getDB'){//如果接收到了getDB,這里讀取數(shù)據(jù)并返回相當(dāng)于初始化popup頁面DBdata('get',function(res){port.postMessage(res.LocalDB);//發(fā)送到popup});}else{//如果不是,則說明是收到來自popup手動(dòng)點(diǎn)擊設(shè)置的數(shù)據(jù),存入以用于popup打開時(shí)展示DBdata('set','',receivedMsg)}}) });
  • 重載插件

  • 這個(gè)時(shí)候會(huì)發(fā)現(xiàn)有兩個(gè)報(bào)錯(cuò)

    發(fā)現(xiàn)是用script引入的jquery報(bào)跨域

    那么就改為文件引入唄

  • 在js目錄下新建jquery.js

    到https://jquery.com/download/去下載production版本的js

    然后把他的內(nèi)容放到j(luò)query.js中

  • 修改popup.html文件中的jquery引入

    <script src="../js/jquery.js"></script>
  • 重載插件,發(fā)現(xiàn)報(bào)錯(cuò)都好了

  • 測試

    每次重置勾選的問題已經(jīng)好了

  • content部分

    content可以注入到瀏覽的網(wǎng)頁,操作dom,所以就可以實(shí)現(xiàn)很多功能了

  • manifest.json中加入content的配置
  • "content_scripts":[{"js":["js/jquery.js","js/content.js"],/*content可以隨意引入js,因?yàn)槠鋬?nèi)容會(huì)在瀏覽的網(wǎng)頁上直接運(yùn)行*/"matches":["*://localhost/*"],/*在哪些網(wǎng)頁上運(yùn)行*/"run_at":"document_end"/* 在頁面加載完成時(shí)運(yùn)行 */ }]

    注意這里現(xiàn)在只是匹配的localhost哦

  • 新建js/content.js,在content.js中寫入

    //content.js manifest匹配地址的頁面在刷新時(shí)會(huì)直接執(zhí)行這里的代碼 chrome.runtime.sendMessage(chrome.runtime.id, {//當(dāng)頁面刷新時(shí)發(fā)送到bgfromContent: 'getDB' });chrome.runtime.onMessage.addListener(function(senderRequest, sender, sendResponse) {//接收到bgconsole.log('demo已運(yùn)行');var LocalDB=senderRequest.LocalDB;console.log(LocalDB);switch(LocalDB.Direct){case 'TEST':console.log(123123);break;default:break;}// 不寫會(huì)報(bào)錯(cuò) Unchecked runtime.lastError: The message port closed before a response was received.sendResponse('這里是content返回值'); });
  • 然后background.js中加入監(jiān)聽content的代碼

    //background.js chrome.runtime.onMessage.addListener(function (senderRequest, sender, sendResponse) {//接收到content// 不寫會(huì)報(bào)錯(cuò) 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) {//從本地取數(shù)據(jù)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的回調(diào)', res);});//發(fā)送到content });break;default:break;}}});} });

    這里注意sendResponse這個(gè)方法,有的沒有在回調(diào)中加上這個(gè)參數(shù),導(dǎo)致找不到

  • 重載插件

  • 代碼執(zhí)行順序

  • 插件初始化階段

  • 先執(zhí)行插件初始化監(jiān)聽background.js中onInstalled,清除本地?cái)?shù)據(jù)
  • 手動(dòng)點(diǎn)擊插件圖標(biāo),勾選插件

  • 執(zhí)行popue.js的ready方法進(jìn)行初始化
  • 點(diǎn)擊按鈕觸發(fā)click方法修改本地?cái)?shù)據(jù)
  • 網(wǎng)頁刷新階段

  • 執(zhí)行content.js的sendMessage方法
  • 執(zhí)行background.js的onMessage方法
  • 讀取本地?cái)?shù)據(jù)
  • 根據(jù)本地?cái)?shù)據(jù)決定是否sendMessage到content
  • 去廣告插件

    說明:這里對(duì)于廣告的判斷是類名為 .ad 的元素

    如我的vue頁面

    <div><h2 class="ad">第一條廣告</h2><h2 class="ad">第二條廣告</h2><h2 class="ad">第三條廣告</h2><h2>這里是正常的數(shù)據(jù)</h2> </div>
  • 在popup.html中增加一個(gè)去廣告按鈕

    <div class="btn">去廣告<input id="removeAD" class="checkbtn" type="checkbox" /> </div>
  • 在background.js中監(jiān)聽content部分增加對(duì)于removeAD的判斷

    //如果是存入的removeAD按鈕 case 'removeAD':chrome.tabs.query({active: true, currentWindow: true}, function(tabs){chrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB});//發(fā)送到content });break;
  • 在content.js中監(jiān)聽background.js部分增加removeAD的判斷

    case 'removeAD'://隱藏含有ad的元素,來達(dá)到去廣告的效果$(".ad").hide();break;
  • 重載插件,勾選頁面中的去廣告,然后刷新頁面,發(fā)現(xiàn)廣告已經(jīng)沒有了

  • 頁面跳轉(zhuǎn)和cookie

    和popup一樣,content關(guān)閉之后也不會(huì)保存數(shù)據(jù),當(dāng)我們?cè)贏頁面獲取數(shù)據(jù)之后想要放到B頁面上去,在content直接跳轉(zhuǎn)是不會(huì)把獲取到的數(shù)據(jù)傳過去的,所以和background鏈接保存本地?cái)?shù)據(jù)就派上用場了

    案例:將csdn的cookie的UserNick顯示在localhost:8081中

  • 在manifest.json中配置【域名腳本匹配】、【權(quán)限】和【主機(jī)權(quán)限】

    "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,否則可能引起頁面腳本無反應(yīng)或者獲取不到cookie

  • 在popup.html中增加按鈕

    <div class="btn">csdn<input id="checkCsdnUserNick" class="checkbtn" type="checkbox" /> </div>
  • 在background.js中增加對(duì)于csdn按鈕的判斷

    case 'checkCsdnUserNick':console.log('LocalDB', LocalDB)//popup設(shè)置數(shù)據(jù)的時(shí)候有個(gè)step屬性,在多步操作的時(shí)候就開始發(fā)揮作用了if(LocalDB.step==0){LocalDB.step = 1;//將step設(shè)置成1chrome.storage.local.set({LocalDB: LocalDB//保存到本地?cái)?shù)據(jù)},function() {chrome.tabs.update(null, {//將前臺(tái)頁面跳轉(zhuǎn)到設(shè)置的url// 這里的url不用帶斜杠 /url: 'https://www.csdn.net'});});}else if(LocalDB.step==1){//因?yàn)閏sdn的地址我們也匹配了所以content在跳轉(zhuǎn)到csdn之后會(huì)還是會(huì)回來,不同的是step已經(jīng)是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;//把獲取到的值放到本地?cái)?shù)據(jù)的cookie屬性里LocalDB.step = 2;//將step設(shè)置成2chrome.storage.local.set({//獲取到cookie之后跳轉(zhuǎn)到第二個(gè)頁面LocalDB: LocalDB//保存到本地?cái)?shù)據(jù)},function() {chrome.tabs.update(null, {//將前臺(tái)頁面跳轉(zhuǎn)到設(shè)置的urlurl: 'http://localhost:8081/'});});});}else if(LocalDB.step==2){//第二步chrome.tabs.query({active: true, currentWindow: true}, function(tabs){//發(fā)送到contentchrome.tabs.sendMessage(tabs[0].id, {LocalDB: LocalDB}); });}break;
  • 在content.js中增加對(duì)于csdn按鈕的判斷

    case 'checkCsdnUserNick':if(LocalDB.step==2){$("body").append('<h1>'+LocalDB.cookie+'</h1>');}break;
  • 重載插件,到csdn.net中開啟插件,勾選csdn,然后刷新頁面就能看到效果

    會(huì)獲取csdn.net中cookie中的昵稱,然后跳轉(zhuǎn)到localhost:8081,進(jìn)行顯示

  • 過程中問題記錄

  • Unchecked runtime.lastError: The message port closed before a response was received.

    這個(gè)問題通常是由于其他插件引起的,注意排查,找到受影響的插件禁用即可

    大多數(shù)人是由于【迅雷】插件或者【油猴】插件引起的

  • 擴(kuò)展【移除】旁邊多了一個(gè)【錯(cuò)誤】的按鈕

  • 如果有錯(cuò)誤提示,根據(jù)提示排查即可

  • 如果沒有錯(cuò)誤提示,嘗試將擴(kuò)展移除重新加載即可

  • 檢查是否沒有把sendMessage和sendResponse配套使用

    每一個(gè)sendMessage都需要和sendResponse進(jìn)行呼應(yīng)

    也就是說,在每一個(gè)chrome.runtime.onMessage.addListener的回調(diào)函數(shù)中,需要使用sendResponse進(jìn)行返回

    可以參見https://blog.csdn.net/m0_37729058/article/details/89186257

  • service worker看不到content.js的console.log

    原因是因?yàn)檫@個(gè)js是嵌入到頁面中的,所以需要在使用的網(wǎng)頁的控制臺(tái)查看,而不是service worker

  • 無法獲取到cookie

    可能原因如下

  • 沒有授權(quán)host_permissions,控制臺(tái)會(huì)報(bào)錯(cuò)Unchecked runtime.lastError: No host permissions for cookies at url: "https://www.csdn.net/".

    檢查manifest.json中的此項(xiàng)配置,沒有添加或者沒有匹配上都會(huì)造成這個(gè)問題

  • 檢查chrome.cookies.get這個(gè)方法中的url是否完全正確

  • 代碼地址

    github跳轉(zhuǎn)

    總結(jié)

    以上是生活随笔為你收集整理的chrome插件开发入门-保姆级攻略的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。