谷歌插件笔记08——练习,完成一个小扩展

87 阅读3分钟

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

相关简介

  • 前言 之前已经简单了解了谷歌扩展的基础知识点,现在就通过利用这些基础的知识点,编写一个简单的谷歌扩展。通过练习来,再次回忆这些谷歌扩展的特性。

  • 介绍 这个谷歌扩展的需求是:扫描页面中的a标签后,插入样式和脚本,当鼠标移入a标签时,显示是从当前页面打开或者是从新标签页面中打开的信息,然后根据设置的不同状态进行不同的打开方式。

开始

思路

  1. 通过使用popup.html弹窗页面来进行打开方式的配置;
  2. 通过使用storage缓存API来保存设置好的打开方式信息;
  3. 通过content_scripts来实现页面打开的脚本逻辑和样式修改。

实现

先来看看manifest.json文件配置(名字随便取了),主要是配置action(弹窗界面)和权限申请还有content_scripts的配置,代码如下:

{
  "name": "易跳转",
  "description": "让页面中的链接跳转更加便捷",
  "version": "0.0.1",
  "manifest_version": 3,
  "action": {
    "default_title": "易跳转",
    "default_icon": "logo.jpeg",
    "default_popup": "popup.html"
  },
  "permissions": ["storage"],
  "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "css": ["static/css/index.css"],
      "js": ["static/js/content.js"]
    }
  ]
}

对于popup页面,设计一个按钮,通过监听点击按钮事件,对样式和缓存的打开方式值进行修改,代码分别如下所示:

<div class="app">
    <div class="app-item">
      <p>默认跳转方式:</p>
      <div class="app-btn">
        <div class="self">当前页打开</div>
      </div>
    </div>
</div>
(async () => {
  const btn = document.querySelector('.app-btn')
  const childEl = btn.querySelector('div')
  const classList = childEl.classList
  const storage = await chrome.storage.sync.get('type')
  const type = storage.type
  if (type === 'self') {
    classList.remove('blank')
    classList.add('self')
    childEl.innerText = '当前页打开'
  } else {
    classList.remove('self')
    classList.add('blank')
    childEl.innerText = '新标签打开'
  }

  btn.addEventListener('click', () => {
    if (classList.contains('self')) {
      classList.remove('self')
      classList.add('blank')
      childEl.innerText = '新标签打开'
      chrome.storage.sync.set({ type: 'blank' })
    } else {
      classList.remove('blank')
      classList.add('self')
      childEl.innerText = '当前页打开'
      chrome.storage.sync.set({ type: 'self' })
    }
  })
})()

以上通过读取缓存中的type值(打开方式的类型),然后根据不同的type来设置文案和类名,然后通过content_scripts注入的CSS来修改不同的样式,这样就能完成切换状态的功能了。
如果代码一切顺利没有Bug的话,就应该有类似如下图的功能了:

crx04.gif

设计好popup后,就是完成关键的content_scripts了,设计思路就是:通过读取缓存的打开方式的状态,然后进行不同状态对应的处理,代码如下:

// static/js/content.js
(async () => {
  const storage = await chrome.storage.sync.get('type')
  const type = storage.type || 'self'
  const links = document.querySelectorAll('a')
  links.forEach(link => {
    const types = Array.from(link.childNodes).map(node => node.nodeName)
    const blackList = ['IMG']
    const isFailed = types.some(type => blackList.includes(type))
    if (!isFailed) {
      link.classList.add('v_link_')
      link.target = type === 'self' ? '_blank' : '_self'
      const el = document.createElement('div')
      el.classList.add('v_link_right')
      el.innerHTML = `
        <a class="v_link_btn" target="${type === 'self' ? '_self' : '_blank'}" href="${link.href}">${type === 'self' ? '当前页打开' : '新标签打开'}</a>
      `
      link.appendChild(el)
    }
  })
})()

注意
上面可以通过设置一个黑名单的方式,来操作希望不被插件重新修改的元素类型,例如IMG

以上通过querySelectorAll查询所有的a标签,通过缓存的type值,动态修改标签中的内容,并且追加一个新的子元素,进行显示另一种打开方式的内容。
例如:当前设置的打开方式是_blank(新标签中打开),那么页面中原始的a标签的target就要设置为_self,然后移入a标签后显示另一个为_blank的打开方式界面。
完成content_scripts的脚本编写顺利的话,就可以看到下图的结果了:

crx05.gif

可以看到,当移入a标签时,弹出了一个可以选择打开方式的界面,即通过popup设置的打开方式,例如为新标签打开方式,那么原始的链接就是当前页打开的方式了。

至此,就已经完成一个简单的谷歌扩展了:)