谷歌插件笔记03——常驻脚本,身后的侍者

·  阅读 36
谷歌插件笔记03——常驻脚本,身后的侍者

持续创作,加速成长!这是我参与「掘金日新计划 · 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"
  }
}
复制代码

执行完成后,进入插件扩展界面刷新扩展,就会看到下图:

image.png

从上图可以看到之前没有的Service Worker栏,这就表明了已经正确配置好了一个服务工作者,此时点击该链接推弹出一个和「开发者工具」一样的调试面板,写的功能就可以通过该界面进行调试。

注意
服务工作者文件"service_worker"必须位于扩展所在的根目录中。

优化「石头剪刀布」游戏

因为之前的弹窗游戏「石头剪刀布」保存的游戏胜负记录在弹窗消失后就会被重置,所以借助background的服务工作者(service_worker)常驻脚本,来解决该问题。代码优化思路为:

  1. 通过在background中定义个对象来保存胜负信息,并且监听popup传来的胜负信息来更新数据;
  2. popup中沿用之前的逻辑,但是当判定胜负后,不再是直接自增变量,而是发送消息给background后,获得响应再进行累加;
  3. popup每次打开时,获得background保存的对象,初始化胜负记录。

思路清楚后,不难完成以下功能,如下图:

crx01.gif

可以看到已经实现了即使关了弹窗后,数据依然可以保存下来,现在就分析以下代码里面究竟修改了哪些地方来完善这个小功能的,代码如下:

// 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(
      callbackfunction
    )
    复制代码

    首次安装扩展程序、扩展程序更新到新版本以及 Chrome 更新到新版本时触发。

    onMessage

    chrome.runtime.onMessage.addListener(
      callbackfunction
    )
    复制代码

    当扩展进程(通过 runtime.sendMessage)或内容脚本(通过 tabs.sendMessage)发送消息时触发。

  • Method

    sendMessage

    chrome.runtime.sendMessage(
      extensionId?: string,
      message: any,
      options?: object,
      callback?: function
    )
    复制代码

    向扩展程序/应用程序或不同的扩展程序/应用程序中的事件侦听器发送一条消息。

上面3个Api只是chrom.runtime下的一部分而已,其他的还有一系列的好用API方法、事件或属性等,在开发中碰到一些问题时,即可前往chrome.runtime文档中查看。
至此,就已经认识这位身后的侍者了:)

分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改