--- title: 修改web页面 slug: Mozilla/Add-ons/WebExtensions/Modify_a_web_page translation_of: Mozilla/Add-ons/WebExtensions/Modify_a_web_page ---
{{AddonSidebar}}

浏览器附加组件( add-on )常被用于修改网页。例如更改页面的样式,隐藏特定的DOM节点或把DOM节点注入到页面中。

使用WebExtensions有两种方式:

无论使用上面何种方式,它们都被称为内容脚本, 与其他脚本的区别:

在本文中,我们将看下加载脚本的两种方式。

修改匹配URL的页面

首先,创建一个名为“ modify-page ”的文件夹,并在目录下创建“ manifest.json ”文件,内容如下:

{

  "manifest_version": 2,
  "name": "modify-page",
  "version": "1.0",

  "content_scripts": [
    {
      "matches": ["https://developer.mozilla.org/*"],
      "js": ["page-eater.js"]
    }
  ]

}

"content_scripts"指出符合 URL 格式的页面地址,然后让浏览器加载脚本(“ page-eater.js“)到匹配的URL页面(https://developer.mozilla.org/ )。

由于 content_scripts "js" 属性是一个数组,因此可以使用它将多个脚本注入匹配的页面。 如果这样做,页面将按照数组中列出的顺序加载多个脚本。

content_scripts 键还具有一个 "css" 属性,可以使用它来注入CSS样式表。

在 "modify-page" 文件夹下创建“ page-eater.js ”文件,内容如下:

document.body.textContent = "";

var header = document.createElement('h1');
header.textContent = "This page has been eaten";
document.body.appendChild(header);

现在安装这个WebExtension, 然后浏览 https://developer.mozilla.org/

{{EmbedYouTube("lxf2Tkg6U1M")}}

请注意,虽然此视频显示在 addons.mozilla.org 工作的 content scripts ,但目前该网站已禁止 content scripts

通过程序修改页面

如何修改程序使其在用户要求时才吞页面。现在修改上面的例子,在点击右键菜单项时才注入内容脚本。

修改 "manifest.json" 内容如下:

{

  "manifest_version": 2,
  "name": "modify-page",
  "version": "1.0",

  "permissions": [
    "activeTab",
    "contextMenus"
  ],

  "background": {
    "scripts": ["background.js"]
  }

}

这里我们要移除"content_scripts"键值,并添加两个键:

在 "modify-page" 文件夹下创建名为 "background.js"的新文件,内容如下:

browser.contextMenus.create({
  id: "eat-page",
  title: "Eat this page"
});

browser.contextMenus.onClicked.addListener(function(info, tab) {
  if (info.menuItemId == "eat-page") {
    browser.tabs.executeScript({
      file: "page-eater.js"
    });
  }
});

在该脚本中我们创建了一个右键菜单项, 给了它一个具体的 id 和标题 (将在菜单中显示的文本)。 然后又设置了一个事件侦听器,当用户点击菜单项时,检查该菜单项是否就是我们的吞页菜单项。 如果是, 就通过tabs.executeScript() 接口,把"page-eater.js" 注入到活动标签页中。 这个接口用标签ID做为参数:如果省略标签ID参数,就默认把脚本注入当前活动标签。

现在,附加组件看起来像这样:

modify-page/
    background.js
    manifest.json
    page-eater.js

重新加载WebExtension, 打开页面 (这次可以是任何一个页面) 激活右键菜单,然后选择 "Eat this page":

{{EmbedYouTube("zX4Bcv8VctA")}}

请注意,虽然此视频显示在 addons.mozilla.org 工作的 content scripts ,但目前该网站已禁止 content scripts

消息

内容脚本和后台脚本不能直接相互访问,但可以通过发送消息进行通信。当一端设置一个消息侦听器时,另一个端就可以发送消息了。下面的表格总结了通信时的api接口:

  在内容脚本中 在后台脚本中
发送消息 browser.runtime.sendMessage() browser.tabs.sendMessage()
接收消息 browser.runtime.onMessage browser.runtime.onMessage

修改上面的示例,使得可以通过后台脚本来发送消息。

首先,修改 "background.js" 如下:

browser.contextMenus.create({
  id: "eat-page",
  title: "Eat this page"
});

function messageTab(tabs) {
  browser.tabs.sendMessage(tabs[0].id, {
    replacement: "Message from the add-on!"
  });
}

browser.contextMenus.onClicked.addListener(function(info, tab) {
  if (info.menuItemId == "eat-page") {
    browser.tabs.executeScript({
      file: "page-eater.js"
    });

    var querying = browser.tabs.query({
      active: true,
      currentWindow: true
    });
    querying.then(messageTab);
  }
});

 注入 "page-eater.js"后, 通过使用 tabs.query() 获取当前活动标签页, 然后使用tabs.sendMessage() 将消息发送到该标签页中的内容脚本。 该消息的内容 {replacement: "Message from the add-on!"}。

接下来,修改 "page-eater.js" 如下:

function eatPage(request, sender, sendResponse) {
  document.body.textContent = "";

  var header = document.createElement('h1');
  header.textContent = request.replacement;
  document.body.appendChild(header);
}

browser.runtime.onMessage.addListener(eatPage);

现在,不再立即执行吞页,内容脚本将先通过使用 runtime.onMessage来监听消息。当监听到消息时, 内容脚本才开始运作,除了来自request.replacement的替换文本不一样以外,其他的脚本运作本质上与之前的相同 。

如果我们想将消息从内容脚本发送到后台页面,除了在内容脚本中使用 runtime.sendMessage() ,其他与上面的过程相反。

这些例子注入的都是JavaScript;注入CSS可以使用 tabs.insertCSS() 函数。

了解更多