前言
- 微前端项目中, 登录模块是集成在主服务中,那么每个子模块都要创建一个独立的登录,就很烦。
- 遇到比较新的关键词想要百度, 那么chrome插件,也有相关api,都可以集成在你的插件中。
- 无聊想划水了,那么偷偷的写个扫雷,五子棋,也可以偷偷摸摸的玩。
- 想获取书签的信息,集成到自己的页面中。重新布局也可以实现。
- 自从看了这篇文章,那你就与浏览器打开了沟通的桥梁。 .....
扬帆起航
1.介绍
每一个扩展、可安装的WebApp、都有一个JSON格式的manifest文件,叫manifest.json,里面提供了重要的信息,这个文件也就是chrome插件.
创建一个
文件夹-> 新建一个manifest.json文件
1.1- manifest.json 详解
{
// 清单文件的版本,这个必须写,而且必须是2, 不过马上更新到3了。
"manifest_version": 2,
// 插件的名称
"name": "小明同学c_chrome插件",
// 插件的版本
"version": "1.0.0",
// 插件描述
"description": "小明同学的chrome插件教学时间",
// 图标,一般偷懒全部用一个尺寸的也没问题
"icons":
{
"16": "img/icon.png",
"48": "img/icon.png",
"128": "img/icon.png"
},
// 会一直常驻的后台JS或后台页面
"background":
{
// 2种指定方式,如果指定JS,那么会自动生成一个背景页
//"page": "background.html"
"scripts": ["js/background.js"]
},
// 浏览器右上角图标设置,browser_action、page_action、app必须三选一
"browser_action":
{
"default_icon": "img/icon.png",
// 图标悬停时的标题,可选
"default_title": "小明同学c的chrome插件",
"default_popup": "index.html"
},
// 当某些特定页面打开才显示的图标
/*"page_action":
{
"default_icon": "img/icon.png",
"default_title": "小明同学c的chrome插件",
"default_popup": "index.html"
},*/
// 需要直接注入页面的JS
"content_scripts":
[
{
//"matches": ["http://*/*", "https://*/*"],
// "<all_urls>" 表示匹配所有地址
"matches": ["<all_urls>"],
// 多个JS按顺序注入
"js": ["js/axios.js", "js/content.js"],
// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式
"css": ["css/index.css"],
// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
"run_at": "document_start"
},
// 这里仅仅是为了演示content-script可以配置多个规则
{
"matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],
"js": ["js/content-script.js"]
}
],
// 权限申请
"permissions":
[
"contextMenus", // 右键菜单
"tabs", // 标签
"notifications", // 通知
"webRequest", // web请求
"webRequestBlocking",
"storage", // 插件本地存储
"http://*/*", // 可以通过executeScript或者insertCSS访问的网站
"https://*/*" // 可以通过executeScript或者insertCSS访问的网站
],
// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
"web_accessible_resources": ["js/injectdom.js"],
// 插件主页,这个很重要,不要浪费了这个免费广告位
"homepage_url": "https://www.baidu.com",
// 覆盖浏览器默认页面
"chrome_url_overrides":
{
// 覆盖浏览器默认的新标签页
"newtab": "newtab.html"
}
}
1.2- 使用
打开chrome浏览器,右上角 ... 竖的标志 -> 更多工具 -> 拓展程序
右上角打开 开发者模式 -> 点击左上角 加载已解压的拓展程序 -> 找到我们刚刚创建的文件夹, 点击确定or选择。即可
1.3 基础描述与图标配置
现在我们已经做好了一个chrome插件了,但是呢,没有功能,还比较丑,现在我们来优化它。都是基础配置, 我就先配置了哈。后面讲通讯再讲重点
"name": "小明同学c_chrome插件",
"version": "1.0.0",
"manifest_version": 2,
"icons": { // 图标配置
"16": "images/icon16.png", // 适用于浏览器tabbar上面的图标配置
"48": "images/icon48.png", // 拓展程序中的 图标配置
"128": "images/icon128.png" //
},
"browser_action": {
"default_icon": "img/icon.png", // 图标
"default_title": "小明的Chrome插件", // 标题
"default_popup": "index.html" // popup页面
}
这里browser_action的 default_popup : 指向的是一个html页面。即点击插件时,所展开的页面。
如何点击登陆调用接口,往浏览器的cookies或者localstorage存放数据呢? 往下看
2.backaground和content_script 怎么实现用户界面的登陆和存储
-
background这里理解为->后台,也可以理解为是你插件的服务端,随时提供为你提供服务的。它随着你的浏览器打开而打开,关闭而关闭。在chrome插件中,
不同的配置项拥有不同的权限,即获取浏览器相关api的权限。,background的权限几乎是最高的,几乎所有的浏览器操作,都是在这个里面完成的。比如存cookies,获取当前tab标签页,获取书签信息....{ // 会一直常驻的后台JS或后台页面 "background": { // 2种指定方式,如果指定JS,那么会自动生成一个背景页 //"page": "background.html" "scripts": ["js/background.js"] } } -
content_script这个是chrome插件向页面注入脚本(js/css)的一种形式, 可以通过该配置,向选中的标签页动态注入css和js,
{ // 需要直接注入页面的JS "content_scripts": { //"matches": ["http://*/*", "https://*/*"], // "<all_urls>" 表示匹配所有地址 "matches": ["<all_urls>"], // 多个JS按顺序注入 "js": ["js/axios.js", "js/content.js"], // JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式 "css": ["css/index.css"], // 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle "run_at": "document_start" }, } -
实现登陆的思路
我们在popup点击按钮触发事件,已知:
backaground是调用chrome浏览器的相关API的,content_script是注入到页面的js。实现: popup中的Click触发,通知
background找到当前选中的tab标签页, 通过content_script注入js执行登陆请求,并存储token, 完事告诉background我执行完了 。通讯:?
-
popup与background与content_script怎么通讯?popup -> background 是可以直接调用 background 中的方法的。
// background.js function sendContentScript (form) { console.log(form) // }// popup.js 即 index.html 中 scirpt 标签引入的js 文件 let bg = chrome.extension.getBackgroundPage(); bg.sendContentScript({ type: 'login', userInfo: { user: '', pass: '' } })background -> content_script 通过
chrome.tabs.sendMessage(tabs[0].id, message, function(){})// background.js function sendContentScript (form) { // active 选中的标签,currentwindow 当前浏览器中的,总结获取tab标签的 chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { //参数1. 获取当前选中的tab标签,参数2,传递的消息体,即参数。 chrome.tabs.sendMessage(tabs[0].id, form, function(response) { console.log(response); // 参数3: 接收消息后的回调函数 }); }) }// content_script // 时刻监听传递来的讯息 chrome.extension.onMessage.addListener( // 参数1. 请求时的消息体,参数 // 参数2:当前选择的浏览器的信息 function(request, sender, sendResponse) { // 即backgroundjs中的参数3 sendResponse("content_scripts回复处理结果"); if (request.type === 'login') { goLogin(request.userInfo) // } } )请求完成后,想告诉backgroundjs 来个桌面通知的消息,即 content -> background
// content_script function success() { chrome.runtime.sendMessage({ type: 'success' }); }// background.js chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.type === 'success') { chrome.notifications.create(null, { type: 'basic', iconUrl: 'img/icon.png', title: 'Julius-通知', message: '登录成功,开启开发者模式~' }); } }) -
刚刚通信已经基本讲到了,哪应该有即时通信吧。真有
这里再单独说明一下。Chrome插件中有2种通信方式,一个是短连接(chrome.tabs.sendMessage和chrome.runtime.sendMessage),一个是长连接(chrome.tabs.connect和chrome.runtime.connect)
短连接的话就是挤牙膏一样,我发送一下,你收到了再回复一下,如果对方不回复,你只能重新发,而长连接类似WebSocket会一直建立连接,双方可以随时互发消息。
示例:
// popup -
function connect () {
chrome.tabs.query({active: true, currentWindow: true},function(tabs) {
let tabId = tabs[0].id
var port = chrome.tabs.connect(tabId, {name: 'connect'});
console.log(port);
port.postMessage({message: '你是谁?'});
port.onMessage.addListener(function(msg) {
if(msg.content && msg.content.startsWith('我是')) {
port.postMessage({message: '哦,原来是你!'});
}
});
})
}
// content_script
chrome.runtime.onConnect.addListener(function(port) {
console.log(port);
if(port.name == 'connect') {
port.onMessage.addListener(function(msg) {
if(msg.message == '你是谁?') port.postMessage({content: '我是你爸!'});
});
}
});
总结
-
通信概述
| 标题 | content-script | popup-js | background |
|---|---|---|---|
| content-script | - | chrome.runtime.sendMessage chrome.runtime.connect | chrome.runtime.sendMessage chrome.runtime.connect |
| popup-js | chrome.tabs.sendMessage chrome.tabs.connect | - | chrome.extension. getBackgroundPage() |
| background | chrome.tabs.sendMessage chrome.tabs.connect | chrome.extension.getViews | - |
- 权限概述
| | JS种类 | 可访问的API | DOM访问情况 | JS访问情况 | 直接跨域 |
|---|---|---|---|---|
| content script | 只能访问 extension、runtime等部分API | 可以访问 | 不可以 | 不可以 |
| popup js | 可访问绝大部分API | 不可直接访问 | 不可以 | 可以 |
| background js | 可访问绝大部分API | 不可直接访问 | 不可以 | 可以 |
看完这个回想刚刚 好像可以直接在popup直接与content_script通信了,都不用经过background了, 对吧。嘿嘿...
- 调试概述
JS类型 | 调试方式 | 图片说明 |
| --------------- | -------------- | ---------------------------------------------------------------------------------------------- | |
| content-script | 打开Console,如图切换 | |
| popup-js | popup页面右键审查元素 |
|
| background | 插件管理页点击背景页即可 |
- 设置右键搜索小工具
// 设置百度搜索
chrome.contextMenus.create({
title: '小明同学Go:%s', // %s表示当前选中的文字
contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
onclick: function(params) {
// 注意不能使用location.href,因为location是属于background的window对象
chrome.tabs.create({url: 'https://www.baidu.com/s?ie=utf-8&wd=' + encodeURI(params.selectionText)});
}
});
- 成品
点关注,不迷路,感谢观看