构建一个简单的 Chrome 扩展程序功能要求入门让我们开始编码

2025-06-07

构建一个简单的 Chrome 扩展程序

功能需求

入门

让我们开始编码

我决定做我的第一个实验Chrome Extension。我的同事提出了一个非常简单的实现想法,所以我决定尝试一下。

功能需求

创建一个Chrome Extension将在页面左上角输出一个小的彩色方块,提醒您domain (i.e. .dev, .stage)当前处于哪种类型的页面。这些domains页面colors将在 上进行管理Options Page

选项页面

及其environments对应的color应该在 上进行管理Options Page,允许您添加/删除任意数量的条目。

活动标签

小方块应该只出现在domains用户添加的匹配条目上Options Page

方块的背景颜色将反映当前条目。

入门

我最初是按照本教程开始的。

每个扩展都需要一个manifest.json。有关选项的完整列表,请访问其官方文档

下面是一个最简单的例子manifest.json

{
  "name": "Environment Flag Example",
  "version": "1.0",
  "description": "Environment Flag Example Extension",
  "manifest_version": 2,
  "background": {},
  "permissions": [],
  "options_page": "",
  "content_scripts": []
}
Enter fullscreen mode Exit fullscreen mode

值得注意的设置

背景脚本

文档

扩展程序是基于事件的程序,用于修改或增强 Chrome 浏览体验。事件是浏览器触发器,例如导航到新页面、移除书签或关闭标签页。扩展程序会在后台脚本中监控这些事件,然后根据指定的指令做出反应。

我们将使用它来向事件中background scripts添加一个event listeneronInstalled

这将允许我们在安装时运行代码extension。我们将使用它event为添加一些默认条目Options Page

{
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  }
}
Enter fullscreen mode Exit fullscreen mode

为什么persistent标记为false?如文档所述:

唯一需要保持后台脚本持续活跃的情况是扩展程序使用 chrome.webRequest API 来阻止或修改网络请求。webRequest API 与非持久性后台页面不兼容。

权限

文档

要使用大多数 chrome.* API,您的扩展程序或应用必须在清单的“权限”字段中声明其意图。

例如,如果您想使用 Chrome 的存储 API,则必须请求权限storage

{
  "permissions": ["storage"]
}
Enter fullscreen mode Exit fullscreen mode

选项页面

文档

此条目将告诉 Chromehtml您想要使用哪个文件作为Options Page您的Extension

{
  "options_page": "options/options.html"
}
Enter fullscreen mode Exit fullscreen mode

您可以通过点击Options下拉菜单中的 来访问此页面Extension

选项菜单项

内容脚本

文档

内容脚本是在网页上下文中运行的文件。通过使用标准文档对象模型 (DOM),它们能够读取浏览器访问的网页的详细信息,对其进行更改,并将信息传递给其父扩展程序。

本质上,任何你想在给定页面上实际运行的脚本都需要利用这一点api。在我们的例子中,我们将在页面的左上角注入一个彩色方块active tab

"content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content/content.js"]
    }
  ]
Enter fullscreen mode Exit fullscreen mode

我还建议观看有关内容脚本和孤立世界的视频,以便更好地了解幕后发生的事情。

我们还需要更新我们的权限以使用activeTab

{
  "permissions": ["storage", "activeTab"]
}
Enter fullscreen mode Exit fullscreen mode

完全的manifest.json

{
  "name": "Environment Flag Example",
  "version": "1.0",
  "description": "Environment Flag Example Extension",
  "manifest_version": 2,
  "permissions": ["storage", "activeTab"],
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "options_page": "options/options.html",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content/content.js"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

让我们开始编码

整个代码库可以在我的github repo中找到。

额外奖励——对于纯粹主义者来说,我创建了一个没有依赖关系的分支

安装

安装开发扩展已经有很好的文档记录,所以我就不再赘述了。

继续并遵循他们的官方文档

背景脚本

我们应该做的第一件事是使用 chrome 的存储 API设置一些默认数据。

本教程需要了解的两种方法是:

chrome.storage.sync.set({ key: value }, function() {
  console.log('Value is set to ' + value);
});

chrome.storage.sync.get(['key'], function(result) {
  console.log('Value currently is ' + result.key);
});
Enter fullscreen mode Exit fullscreen mode

second parameter操作完成后,每个方法都会执行一次callback functionstorage我们将利用它来Vue更新内部状态。

让我们打开background.js并添加一个扩展事件installed

// background.js

chrome.runtime.onInstalled.addListener(function() {
  /**
   * lets add a default domain
   * for our options page
  */
  chrome.storage.sync.set(
    {
        config: [
            {
                domain: 'docker',
                color: '#2496ed',
            },
        ],
    },
    null
  );
}
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们执行以下操作:

  1. storage object向被叫添加新键config
  2. 对于以 结尾的域名,entry添加一个configdocker

选项页面

对于我的技术栈,我决定使用Bootstrap 4Vue JSWebpack和原生ES6 JavaScript。我选择这些是因为我对它们很熟悉,但你也可以自由选择你自己的。

出于本教程的目的,我不会对 Vue 进行太多解释,因为它是一个实现细节,并且不是构建扩展所必需的。

对于无依赖的实现,请查看此分支

options.html页面非常简单:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta content="width=device-width, initial-scale=1.0" name="viewport" />
    <meta content="ie=edge" http-equiv="X-UA-Compatible" />
    <title>Environment Flag Options</title>
    <link
      crossorigin="anonymous"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
      integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO"
      rel="stylesheet"
    />
  </head>
  <body>
    <main>
      <div class="container  py-5">
        <div class="col-sm-8  offset-sm-2">
          <div id="app"></div>
        </div>
      </div>
    </main>
    <script src="../dist/options.bundle.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

在继续之前,先看看选项文件夹Vue。这是一个非常标准的应用程序。

让我们回顾一些值得注意的Vue代码。Options.vue大多数神奇的事情都是利用发生的chrome api

// options/Options.vue

{
    data() {
        return {
            /**
             * empty array to be used to store
             * the chrome storage result
             */
            config: [],
        };
    },
    mounted() {
        /**
         * once the component mounts
         * lets call the storage api
         * and request our `config` key
         * 
         * on our callback, lets call a method
         * to set our internal state
         */
        chrome.storage.sync.get(['config'], this.setConfig);
    },
    methods: {
        setConfig(storage) {
            /**
             * set our internal state
             * with the result from the
             * chrome api call
             */
            this.config = storage.config;
        },
    },
}
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们执行以下操作:

  1. 设置名为的键的内部状态config,并将其分配给空array
  2. mounted()方法中,我们请求config密钥storage api
  3. callback function,我们调用一个方法this.setConfig
  4. setConfig()将我们的内部状态分配给从chrome api

然后我们有两种方法来改变chrome storage state

{
    deleteEntry(index) {
        /**
         * remove the entry at a specific index
         * from our internal state
         */
        this.config.splice(index, 1);

        /**
         * update the chrome storage api
         * with the new state
         */
        chrome.storage.sync.set(
            {
                config: this.config,
            },
            null
        );
    },
    addEntry(entry) {
        /**
         * add an entry to our internal state
         */
        this.config.push(entry);

        /**
         * update the chrome storage api
         * with the new state
         */
        chrome.storage.sync.set(
            {
                config: this.config,
            },
            null
        );
    },
}
Enter fullscreen mode Exit fullscreen mode

实现这些方法之后,最终的Options Page效果是这样的:

选项页面已完成

我知道,没什么特别的……但这不是重点。出去玩玩吧!你会注意到我添加了一个edu域名,如果你愿意的话,现在就添加吧。

内容脚本

现在我们有了一种Options Page方法add / delete entries,现在让我们实现将出现在有效域左上角的小方块。

为此,我们需要使用content script之前讨论过的方法。让我们继续,打开content/content.js文件。

// content/content.js

/**
 * lets first request the `config` key from
 * the chrome api storage
 */
chrome.storage.sync.get(['config'], ({ config }) => {
  /**
   * lets see if the `window.location.origin`
   * matches any entry from our
   * options page
   */
  let match = config.find((entry) => {
    let regex = RegExp(`${entry.domain}\/?$`);

    return regex.test(window.location.origin);
  });

  /**
   * if no match, don't do anything
   */
  if (!match) return;

  /**
   * lets create the style attribute
   * by building up an object
   * then using join to combine it
   */
  let node = document.createElement('div');
  let nodeStyleProperties = {
    'background-color': match.color,
    height: '25px',
    left: '5px',
    opacity: 0.5,
    'pointer-events': 'none',
    position: 'fixed',
    top: '5px',
    width: '25px',
    'z-index': '999999',
  };
  let nodeStyle = Object.entries(nodeStyleProperties)
    .map(([key, value]) => {
      return `${key}: ${value}`;
    })
    .join('; ');

  /**
   * apply the style to the node
   * and a class flag (doesn't do anything)
   */
  node.setAttribute('style', nodeStyle);
  node.setAttribute('class', 'chrome-extension-environment-flag');

  /**
   * append the node to the document
   */
  document.body.appendChild(node);
});
Enter fullscreen mode Exit fullscreen mode

结论

现在,当我进入一个edu域时,我会在左上角看到以下内容:

UMBC主页

我希望本教程至少能让你对 Chrome 扩展程序感兴趣。我们只是粗略地介绍了一些内容。欢迎将我仓库中的任何代码用于任何用途。

文章来源:https://dev.to/michaeldscherr/building-a-simple-chrome-extension-1mal
PREV
想要工作经验?我们正在寻找开发人员
NEXT
如何成长为一名开发人员