持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
相关简介
-
前言 在完成
popup弹窗的配置之后,已经可以通过点击插件显示一个页面。但是,该页面的生命周期比较短,只有当出现的时候才会执行相关功能,当未打开页面想做一些事儿时,就没有办法了。要想解决这个问题,就得引入插件中德后台脚本文件。 -
介绍 在清单
manifest.json文件中,可以通过配置background字段来指定一个后台脚本,该脚本可以是.js文件也可以是.html文件(系统会自动生成js文件),并且该文件能调用大部分谷歌内置接口。
Background
首先在根目录新建一个background.js文件,然后再manifest.json清单文件中配置如下字段:
// manifest.json
{
"name": "hello",
"description": "hello description",
"version": "0.0.1",
"manifest_version": 3,
"action": {
"default_title": "popup title",
"default_icon": "logo.png",
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
}
}
执行完成后,进入插件扩展界面刷新扩展,就会看到下图:
从上图可以看到之前没有的Service Worker栏,这就表明了已经正确配置好了一个服务工作者,此时点击该链接推弹出一个和「开发者工具」一样的调试面板,写的功能就可以通过该界面进行调试。
注意
服务工作者文件"service_worker"必须位于扩展所在的根目录中。
优化「石头剪刀布」游戏
因为之前的弹窗游戏「石头剪刀布」保存的游戏胜负记录在弹窗消失后就会被重置,所以借助background的服务工作者(service_worker)常驻脚本,来解决该问题。代码优化思路为:
- 通过在
background中定义个对象来保存胜负信息,并且监听popup传来的胜负信息来更新数据; - 在
popup中沿用之前的逻辑,但是当判定胜负后,不再是直接自增变量,而是发送消息给background后,获得响应再进行累加; - 在
popup每次打开时,获得background保存的对象,初始化胜负记录。
思路清楚后,不难完成以下功能,如下图:
可以看到已经实现了即使关了弹窗后,数据依然可以保存下来,现在就分析以下代码里面究竟修改了哪些地方来完善这个小功能的,代码如下:
// popup.js
const skill = ['剪刀', '石头', '布']
const resultType = ['平局', '你赢了', '你输了']
const resultEle = document.querySelector('.result')
const infoEle = document.querySelector('.info')
const send = (data, callback) => {
chrome.runtime.sendMessage(data, res => {
callback(res)
infoEle.innerHTML = `胜利:${win} </br>平局:${draw} </br>失败:${lose} </br>`
})
}
let win = 0, lose = 0, draw = 0
send({ type: 'get' }, res => {
win = res.win
lose = res.lose
draw = res.draw
})
document.querySelectorAll('button').forEach((btn, idx) => {
btn.addEventListener('click', () => {
const rIdx = Math.floor(Math.random() * 3)
const resultIdx = idx >= rIdx ? idx - rIdx : resultType.length + idx - rIdx
resultIdx > 1
? send({ type: 'lose' }, res => lose = res.lose)
: resultIdx > 0
? send({ type: 'win' }, res => win = res.win)
: send({ type: 'draw' }, res => draw = res.draw)
resultEle.innerHTML = `你出招${skill[idx]},电脑出招${skill[rIdx]}...<br />${resultType[resultIdx]}`
})
})
// background.js
const result = {
win: 0,
lose: 0,
draw: 0
}
chrome.runtime.onInstalled.addListener(() => {
chrome.runtime.onMessage.addListener((req, sender, res) => {
const type = req.type
if (type !== 'get') {
result[type] ++
}
res(result)
})
})
从上面的代码中,可以看到几个以前从未在JavaScript中看到的API方法或事件,例如chrome.runtime.onInstalled等。
而这些Api就是谷歌提供给开发者的,有了这些Api后,就能在开发中大展拳脚了!
这里说明以上用到的chrome.runtime下的Api方法和事件(事件大都需要通过addListener来添加监听器):
-
Event
onInstalled
chrome.runtime.onInstalled.addListener( callback: function )首次安装扩展程序、扩展程序更新到新版本以及 Chrome 更新到新版本时触发。
onMessage
chrome.runtime.onMessage.addListener( callback: function )当扩展进程(通过 runtime.sendMessage)或内容脚本(通过 tabs.sendMessage)发送消息时触发。
-
Method
sendMessage
chrome.runtime.sendMessage( extensionId?: string, message: any, options?: object, callback?: function )向扩展程序/应用程序或不同的扩展程序/应用程序中的事件侦听器发送一条消息。
上面3个Api只是chrom.runtime下的一部分而已,其他的还有一系列的好用API方法、事件或属性等,在开发中碰到一些问题时,即可前往chrome.runtime文档中查看。
至此,就已经认识这位身后的侍者了:)