Chrome 扩展程序 101

2025-05-28

Chrome 扩展程序 101

本博客将讨论如何设置、构建和运行您自己的 Chrome 扩展程序。最后,您将能够创建一个简单的“日期倒计时”扩展程序,显示距离特定日期还有多少天。
展示扩展程序工作原理的 Gif 图像

我们走吧!

Chrome 扩展术语

清单.json

JSON 文件告诉 Chrome 该扩展程序的功能、需要的权限以及将使用的文件。

背景脚本

独立于用户所在网页并与其并行运行的脚本。它用于状态管理,并且始终只有一个活动实例。

内容脚本

在用户所在网页上下文中运行的脚本。它可以访问、读取和/或修改用户所访问页面的 DOM。

设置

为您的扩展程序创建一个文件夹,例如 Count-Down,并在其中创建一个名为 的文件manifest.json。在该文件中,添加清单版本、扩展程序名称、描述以及扩展程序的初始版本。该文件现在应该类似于此。



{
  "manifest_version": 3,
  "name": "Count Down Days",
  "version": "1.0",
  "description": "Takes a date input and displays the number of days left until the given date"
}


Enter fullscreen mode Exit fullscreen mode

文件和文件夹结构

现在我们开始创建其余元素。

  • 根文件夹中有一个名为background.js的文件。这将是我们的后台脚本。
  • 根文件夹中有一个名为content的文件夹,其中包含:
    1. 一个名为popup.html的 HTML 文件。此文件将包含扩展程序下拉菜单的标记
    2. 一个名为popup.js的 JS 文件。这是我们的内容脚本
    3. 一个名为 popup.css 的 CSS 文件,用于设置下拉菜单中的元素样式
  • 图像文件夹(扩展图标和其他 - 可选)

将文件链接到manifest.json

我们将在manifest.json中引用后台脚本和 HTML 文件,如下所示。



"background": {
    "service_worker": "background.js"
  },
"action": {
    "default_popup": "content/popup.html",
    "default_icon": {
        "16": "images/icon16.png",   // optional
        "24": "images/icon24.png",   // optional
        "32": "images/icon32.png"    // optional
     }
  }


Enter fullscreen mode Exit fullscreen mode

图标最初由manifest.json 文件中 action 条目的default_icon键设置。该键接受一个包含图片大小和路径的字典。如果未指定图标,Chrome 会自动分配一个图标。

manifest.json现在应该如下所示



{
  "manifest_version": 3,
  "name": "Count Down Days",
  "version": "0.1",
  "description": "Takes a date input and displays the day count left to the given date ",
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "content/popup.html",
    "default_icon": {
      "16": "/images/timer.png",
      "128": "/images/timer.png",
      "48": "/images/timer.png",
      "256": "/images/timer.png"
  }
  }
}


Enter fullscreen mode Exit fullscreen mode

运行扩展

打开 Chrome 浏览器并点击以下 URL:


 chrome://extensions 

Enter fullscreen mode Exit fullscreen mode

在右上角,您应该会看到一个名为“开发者模式”的切换按钮。
勾选该按钮。
现在,您应该会看到一组用于加载、打包和更新扩展程序的选项。
选择“加载解压后的扩展程序”选项。
现在,从文件系统中选择扩展程序的根文件夹。
扩展程序将加载到浏览器中。

显示浏览器中加载的 Chrome 扩展程序的图像

授予扩展权限

对于此扩展,我们将使用以下权限:

  1. activeTab - 允许访问当前活动的 Chrome 标签页。在本例中,我们需要此权限,因为我们要将标签页添加到当前活动的标签页。
  2. 脚本- 允许在当前网页上下文中运行脚本。我们使用此权限来注入执行日期操作的监听器事件。
  3. 存储- 允许在 Chrome 中存储对象。我们将使用此权限将日期字符串存储在 Chrome 存储中。

在manifest.json中添加以下行

“权限”:[“activeTab”,“存储”,“脚本”]

添加逻辑

打开background.js并添加以下代码:



let date = "08 15 2021";

chrome.runtime.onInstalled.addListener(() => {

    chrome.storage.sync.set({ date });

    console.log("Default Date set to Aug 15, 2021");

});


Enter fullscreen mode Exit fullscreen mode

chrome.runtime是一个 API,允许扩展程序检索后台页面、监听并响应事件。
我们在这里所做的实际上是使用该 API 将一个默认日期字符串保存到 Chrome 存储中。稍后,我们的内容脚本可以访问此值。我们还添加了一个日志语句,用于测试。

在popup.html中,我们添加了两个按钮(一个用于显示剩余天数,另一个用于接受新的日期)。我们在此文件中引用样式popup.css和内容脚本popup.js,如下所示。



<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="popup.css" />
  </head>

  <body>
    <div class="buttons">
      <button id="showDays">
        <img class="img-icon" src="../images/timer.png" alt="Sand Clock" />
      </button>
      <button id="changeDate">
        <img class="img-icon" src="../images/change-date.png" alt="Change Date Icon" />
      </button>
    </div>
    <script src="popup.js"></script>
  </body>
</html>


Enter fullscreen mode Exit fullscreen mode

我为按钮使用了图像图标。资源可在下方 Github 链接中找到。让我们在popup.css文件中添加一些基本样式,如下所示。



button {
  height: 30px;
  width: 30px;
  outline: none;
  margin: 10px;
  border: none;
  border-radius: 2px;
}
button img {
  width: 100%;
  height: auto;
}


Enter fullscreen mode Exit fullscreen mode

当前页面无法访问这些样式。保存后,我们返回浏览器,在chrome://extensions标签页中找到我们的扩展程序。每个扩展程序的右下角都有一个刷新图标。
刷新扩展程序,然后点击Service Worker超链接,即可查看 Service Worker(即background.js)的日志。现在,我们将能够在控制台中看到默认日期日志。

下一步是查看扩展程序的下拉菜单。打开另一个标签页,在 Chrome 浏览器的右上角,新扩展程序将变成一个可点击的选项。点击该选项后,我们将看到如下所示的下拉菜单。

图片显示下拉菜单中有 2 个选项

注意:Chrome 扩展程序无法在chrome:// URL上打开

这些按钮还不会做任何事情,所以让我们添加可以执行魔术的听众。

popup.js中添加以下两个函数



// Content script follows
function showDaysLeft() {
    // get the date string from Chrome storage
    chrome.storage.sync.get("date", ({ date }) => {

        // create a new div that will be appended to the body
        let daysElement = document.createElement("div");
        // adding styles to the new div
        daysElement.style.cssText = "position: absolute; color: black; top: 30px; left: 50%;  transform: translateX(-50%); background-color: pink; z-index: 99999; padding: 1rem; border-radius: 10px; box-shadow: 3px 3px 6px #00000060";
        //  Date.parse converts Date string to milliseconds
        // To get the number of days left we get the difference in milliseconds and divide by 86400000 (milliseconds in a day)
        noOfDaysLeft = parseInt((Date.parse(new Date(date)) - Date.parse(new Date())) / (86400000));
        let content = '';
        if (noOfDaysLeft < 0) {
            content = document.createTextNode("Deadline has already passed.Please set a new one. :D");


            alert(daysElement);
        } else {
            content = document.createTextNode(noOfDaysLeft + " days until go time! B)");

        }
        // Append the text node to the div
        daysElement.appendChild(content);
        // Append the div to the body tag
        document.body.appendChild(daysElement);
        setTimeout(() => {
            document.body.removeChild(daysElement)
        }, 3000);
    });

}

function resetDate() {
    let newDate = " ";
    let daysElement = document.createElement("div");
    daysElement.style.cssText = "position: absolute; color: black; top: 30px; left: 50%; transform: translateX(-50%); background-color: pink; z-index: 99999; padding: 1rem; border-radius: 10px; box-shadow: 3px 3px 6px #00000060";

    // Get the date string input through window.prompt
    newDate = window.prompt("Enter date in the dd/mm/yyyy format");
    dateArray = newDate.split("/");

    dateString = dateArray[1] + " " + dateArray[0] + " " + dateArray[2];

    newDate = Date.parse(new Date(dateString));
    let content = '';
    // Check if the format is right 
    if (newDate) {
        noOfDaysLeft = parseInt((Date.parse(new Date(newDate)) - Date.parse(new Date())) / (86400000));
        if (noOfDaysLeft < 0) {
            content = document.createTextNode("Are you time travelling to the past? I am not ready for you yet :D");


        } else {
            content = document.createTextNode("New date saved! \n" + noOfDaysLeft + " days until go time! B)");

            // save the new date
            chrome.storage.sync.set({ "date": newDate });
        }

    } else {
        content = document.createTextNode("Enter a valid date - date/month/full-year");

    }
    daysElement.appendChild(content);
    document.body.appendChild(daysElement);
    setTimeout(() => {
        document.body.removeChild(daysElement)
    }, 3000);


}



Enter fullscreen mode Exit fullscreen mode

函数逻辑在注释中解释。现在我们不能直接将监听器附加到按钮上。我们使用chrome.scripting API 将监听器注入到当前页面,如下所示:



// Initialize buttons

let showDays = document.getElementById("showDays");
let changeDate = document.getElementById("changeDate");


// When the button is clicked, inject showDaysLeft and resetDate into current page

showDays.addEventListener("click", async () => {

    let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

    chrome.scripting.executeScript({

        target: { tabId: tab.id },

        function: showDaysLeft,

    });

});
changeDate.addEventListener("click", async () => {

    let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });

    chrome.scripting.executeScript({

        target: { tabId: tab.id },

        function: resetDate,

    });

});


Enter fullscreen mode Exit fullscreen mode

注意:除了注入的监听器之外,其他函数/变量不能直接运行。

大功告成!😎 现在扩展程序已准备好进行测试。返回浏览器,刷新扩展程序,然后在新的标签页上测试它。输出结果应该类似于下面的 gif。

展示扩展程序工作原理的 Gif 图像

希望以上内容对您有所帮助。完整项目已发布在Github上。如有任何疑问,请通过Twitter联系我,或在下方评论区留言。✌️

文章来源:https://dev.to/venkyakshaya/chrome-extensions-101-3dif
PREV
使用 VS Code Docker 化 Node.js 应用
NEXT
永远不要在初创公司担任软件工程师!