有没有好奇chrome[1]插件是用什么做的?像类似掘金
插件又是怎么实现的,当我安装稀土掘金插件后,我的导航页都被改掉了,因此你也可以做一个类似的插件,来导航你公司的一些产品,方便快捷的实现你的内部导航
在开始本文之前,主要是从零认识一个chrome
插件,主要会从以下几点去认识chrome插件
- 核心配置
manifest.json
配置,必不可少的几个配置 popup
为插件内容文件background
与content
通信,popup
与content
通信chrome.runtime
几个通信API
正文开始...
首先预知的几个文件
manifest.json
,必须在插件根目录上新建一个这样的文件,我们从官网查看更多的manifest[2]信息
{ // 必不可少 "manifest_version": 3, // 扩展插件版本必须是2以上 "name": "Maic_test_chrome", // 扩展名称 "description": "lesson demo", // 扩展描述 "version": "1.0", // 可选 "action": { "default_popup": "popup/index.html", // 默认的页面 "default_icon": "logo.png" // 浏览器扩展插件显示图标 }, // 在插件列表里显示不同尺寸的图标 "icons": { "16": "images/icon-16.png", "32": "images/icon-32.png", "48": "images/icon-48.png", "128": "images/icon-128.png" } }
让当前网页加载一个脚本
content_scripts
指定加载对应脚本js
,css
注意matches
中匹配的是当前访问的url,当选择<all_urls>
时,匹配任何url,必须要有matches[3]否则不会生效
"content_scripts": [ { "js": [ "scripts/content.js" ], "matches": [ "https://*.wmcweb.cn/*", "<all_urls>" ] } ]
background增强浏览器事件程序的js
{ "background": { "service_worker": "background.js" } }
background.js
与content.js
通信
background.js
在插件页面加载,background.js
调用onMessage.addListener
接收content.js
发送过来的数据
function callback(info, curent, sendToContent) { } chrome.runtime.onMessage.addListener(callback) // background.js 在插件页面加载 const user = { username: 'Maic' }; // 调用onMessage.addListenter chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { console.log('background.js', message, sender) // 2. A page requested user data, respond with a copy of `user` if (message === 'get-user-data') { sendResponse(user); } });
content.js
在你指定的匹配域名页面加载,与当前浏览器加载的页面同环境
content.js
,content
向background.js
发送信息
chrome.runtime.sendMessage(info, callbackResponse)
// sendMessage content.js chrome.runtime.sendMessage('get-user-data', (response) => { console.log('received user data', response); });
popup.js
向content.js
通信
在popup
页面需要查找当前激活的tabs
// popup.js chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.tabs.sendMessage(tabs[0].id, {}, function (response) { console.log(response, 'content.js回传过来的信息'); }); });
在content.js
接收信息
function callback(request, sender, sendResponse) {} chrome.runtime.onMessage.addListener(callback)
content.js
详细代码参考以下
// content.js console.log('loader-content') // 1. content向service worker发送信息 chrome.runtime.sendMessage('get-user-data', (response) => { // 2,接受service worker回调过来的信息 console.log('received service worker data', response); }); const render = ({ style, title }) => { const boxDom = document.querySelector('.box'); const contentDom = document.querySelector('.content'); const resultDom = document.querySelector('.result'); boxDom.style.width = style.width; boxDom.style.height = style.height; boxDom.style.backgroundColor = style.backgroundColor; contentDom.innerText = title; resultDom.innerText = JSON.stringify({ ...style, title }, null, 2) } // 接收popup.js发送过来的信息 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { console.log('content', request, sender); const { inputColorValue, titleValue, widthValue, heightValue } = request; const style = { width: `${widthValue}px`, height: `${heightValue}px`, backgroundColor: inputColorValue } const receivePopupInfo = { style, title: titleValue } // 向popup.js回传信息 sendResponse(receivePopupInfo) render(receivePopupInfo) });
background.js
参考如下
const user = { username: 'Web技术学苑' }; chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { console.log('background.js', message, sender) if (message === 'get-user-data') { sendResponse(user); } });
popup.js
参考如下
const $ = id => document.getElementById(id); function setBadge() { const inputColorValue = $('color-input').value; const titleValue = $('title-input').value; const widthValue = $('width-input').value; const heightValue = $('height-input').value; const info = { inputColorValue, titleValue, widthValue, heightValue } chrome.action.setBadgeText({ text: inputColorValue }); // 扩展脚本向content发出信息 chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { console.log(tabs) chrome.tabs.sendMessage(tabs[0].id, info, function (response) { console.log(response, 'content.js回传过来的信息'); }); }); } $('submit').addEventListener('click', setBadge); ['width', 'height'].forEach(dom => { const curent = $(`${dom}-input`); curent.addEventListener('change', (evt) => { $(`${dom}-result`).innerText = evt.target.value; }) });
我们再看下popup.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <link rel="stylesheet" href="popup.css" /> </head> <body> <div id="app"> <div>title: <input type="text" value="我是标题" id="title-input" /></div> <div>color:<input type="color" id="color-input" /></div> <div> width: <input type="range" value="30" id="width-input" max="1000" /> <span id="width-result">30</span> </div> <div> height: <input type="range" value="30" id="height-input" max="1000" /> <span id="height-result">30</span> </div> <button id="submit">确定</button> </div> <script src="./popup.js"></script> </body> </html>
当你打开浏览chrome://extensions/
然后添加插件04-demo
在打开一个测试页面
我通过插件中的popup.js
与content.js
通信,就可以修改我当前页面上的元素了
另外推荐一个chrome
插件官方的例子chrome-extensions-samples[4],看完一些例子多插件哟更深刻的认识,在下一节里,我会利用chrome
内置缓存能力做一些与我们实际业务相关的例子。
总结
- 一个
chrome
插件基础文件manifest.json
几个比较的参数,加载插件根目录必须要有个文件,且manifest_version
是2
版本上 popup.js
与content.js
交互,content.js
是独立于插件外部脚本,当匹配对应网页时,可以利用content.js
控制当前网页background.js
是运行插件增强js
,我们可以在这background.js
控制chrome
插件,或者与popup.js
的通信chrome
核心api
,chrome.runtime.onMessage
,chrome.runtime.sendMessage
,chrome.tab.query
的使用- 本文示例code example[5]