谷歌插件笔记04——内容脚本,与页面共舞

100 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

相关简介

  • 前言 在前面的介绍中,虽然认识到了popup弹窗还有background后台脚本等的用处,但是思考过后,发现了仍然还有一个问题。那就是,无法和当前所在的页面交互,要做到这个功能就需要引入content_scripts内容脚本了。

  • 介绍

内容脚本content_scripts可以伴随着页面运行,但是它却不会与该页面中的其他脚本或者插件相互产生影响。所以说,内容脚本content_scripts可以说是出于一个封闭的环境当中,默默做着相应的事。

content_scripts

要配置内容脚本content_scripts也很简单,在老朋友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"
  },
  "content_scripts": [
    {
      "matches": ["https://example.com/"],
      "css": [],
      "js": ["static/js/content1.js"]
    }
  ],
  "permissions": ["contextMenus", "scripting"]
}

然后再根据对应的路径,新建content1.js文件,如下:

// static/js/content1.js
console.log('hello content script.')

接着打开谷歌浏览器,输入https://example.com/进入网页,然后通过F12或者右键打开菜单点击「检查」项进入开发者工具,如下:

image.png

可以看到,在控制台上输出了编写的:"hello content script."语句,这样就表明已经成功的配置了content_scripts内容脚本了。

各项配置

完成content_scripts配置后,现在简单来看看上面配置是什么意思,如下:

配置项类型作用
matchesstring[]必选项,指定配置的内容脚本会被注入到哪些页面中
cssstring[]可选的。 要注入匹配页面的 CSS 文件列表
jsstring[]可选的。 要注入匹配页面的 JS 文件列表

了解配置后,从上面matches配置中,可以得知该注入内容只有在https://example.com域中才会注入,在其他页面则不会注入,例如在掘金中打开开发者面板,也不会有打印信息,如下:

了解到这些配置项作用后,再看上面指定的matches配置,此时配置的是https://example.com/网址,表明只有在当前域名下,才会主语对应的content_scripts内容,如下:

image.png

做个Demo

既然已经知道了content_scripts的基本用法了,现在就可以试着练习编写一个Demo程序:收集掘金页面中的文章列表(暂不考虑异步加载),设计思路如下:

  1. 通过content_scripts注入的脚本获取页面中的文章标题和href信息;
  2. 通过storage把文章列表数据缓存起来,等待使用;
  3. popup弹窗中,获取缓存的文章列表数据,回显到页面。

明确思路后,编写如下代码:

// static/js/content.js
function init() {
  const elList = document.querySelectorAll('.entry-list > li .content-wrapper')
  const list = Array.from(elList).map(item => {
    const link = item.querySelector('.title-row > a')
    return {
      title: link.title,
      href: link.href
    }
  })
  chrome.storage.sync.set({
    list
  })
}

setTimeout(() => {
  init()    // 因为是异步的,这里暂时通过setTimeout来处理
}, 1e3)
<body>
  <ul class="list">
  </ul>
  <script src="popup.js"></script>
</body>
//popup.js
chrome.storage.sync.get('list', ({ list }) => {
  const el = document.querySelector('.list')
  let html = ''
  list.forEach(item => {
    html += `
      <li>
        <a href="${item.href}" target="_blank">${item.title}</a>
      </li>
    `
  })
  el.innerHTML = html
})

完成以上代码后,可以看到效果图如下:

crx02.gif

权限申请

在上面代码中,可以看到使用了一个新的Api方法:chrome.storage.sync,使用这个方法时得需要向谷歌申请权限,申请方式为在manifest.json中配置permisstions字段:

{
  "name": "Collection",
  "description": "collection article list",
  "version": "0.0.1",
  "manifest_version": 3,
  "action": {
    "default_title": "collection popup",
    "default_icon": "logo.png",
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["https://juejin.cn/"],
      "js": ["static/js/content.js"]
    }
  ],
  "permissions": ["storage"]
}

在插件开发中,有很多Api都需要申请权限,配置permissions字段的,像这里就是申请了缓存权限,更多的权限可以查看谷歌插件开发的权限申明

另外,更多的「内容脚本」信息可以查看:content_scripts文档

至此,就已经认识这位页面中的舞者了:)