menus.onShown

浏览器显示菜单时触发。

扩展程序可以使用此事件,利用菜单显示后才能获得的信息来更新其菜单项。通常,扩展程序会在其 onShown 处理程序中完成更新,然后调用 menus.refresh() 来更新菜单本身。

处理程序可以添加、删除或更新菜单项。

例如,menu-labelled-open 示例扩展程序会在用户单击链接时显示一个菜单项,该菜单项在单击时会打开该链接。它使用 onShownrefresh() 来用链接的域名注解菜单项,这样用户在单击之前就可以轻松地看到他们将前往何处。

请注意,扩展程序在调用 refresh() 之前不应花费太多时间,否则用户会注意到更新。

处理程序会收到有关菜单及其内容的某些信息,以及来自页面的某些信息(例如链接和/或选定文本)。要访问来自页面的信息,您的扩展程序必须具有该页面的 主机权限

如果 onShown 处理程序调用了任何异步 API,那么在处理程序恢复执行之前,菜单可能已经关闭。因此,如果处理程序调用了任何异步 API,它应该在更新菜单之前检查菜单是否仍在显示。例如:

js
let lastMenuInstanceId = 0;
let nextMenuInstanceId = 1;

browser.menus.onShown.addListener(async (info, tab) => {
  let menuInstanceId = nextMenuInstanceId++;
  lastMenuInstanceId = menuInstanceId;

  // Call an async function
  await doSomethingAsync();

  // After completing the async operation, check whether the menu is still shown.
  if (menuInstanceId !== lastMenuInstanceId) {
    return; // Menu was closed and shown again.
  }
  // Now use menus.create/update + menus.refresh.
});

browser.menus.onHidden.addListener(() => {
  lastMenuInstanceId = 0;
});

请注意,可以同步调用 menus API 函数,在这种情况下,您不必执行此检查。

js
browser.menus.onShown.addListener(async (info, tab) => {
  browser.menus.update(menuId /*, … */);
  // Note: Not waiting for returned promise.
  browser.menus.refresh();
});

但是,如果您异步调用这些 API,则必须执行检查。

js
browser.menus.onShown.addListener(async (info, tab) => {
  let menuInstanceId = nextMenuInstanceId++;
  lastMenuInstanceId = menuInstanceId;

  await browser.menus.update(menuId /*, … */);
  // must now perform the check
  if (menuInstanceId !== lastMenuInstanceId) {
    return;
  }
  browser.menus.refresh();
});

Firefox 通过 contextMenus 命名空间以及 menus 命名空间提供此事件。

语法

js
browser.menus.onShown.addListener(listener)
browser.menus.onShown.removeListener(listener)
browser.menus.onShown.hasListener(listener)

事件有三个函数

addListener(listener)

向此事件添加监听器。

removeListener(listener)

停止监听此事件。listener 参数是要移除的监听器。

hasListener(listener)

检查 listener 是否已为此事件注册。如果正在监听,则返回 true,否则返回 false

addListener 语法

参数

监听器

此事件发生时调用的函数。该函数会传递以下参数:

info

Object。这与 menus.OnClickData 对象非常相似,只是它包含两个额外的属性:

  • contexts:一个数组,包含适用于此菜单的所有 contexts
  • menuIds:一个数组,包含属于此扩展程序且在此菜单中显示的菜单项的 ID。

menus.OnClickData 相比,info 对象还省略了 menuItemIdmodifiers 属性,因为当然这些属性要到菜单项被选中后才能获得。

contextsmenuIdsframeIdeditable 属性始终提供。info 中的所有其他属性仅在扩展程序具有该页面的 主机权限 时才提供。

tab

tabs.Tab。单击发生所在的标签页的详细信息。如果单击未发生在标签页内部或标签页上,则此参数将丢失。

示例

此示例监听链接上显示上下文菜单,然后用链接的域名更新 openLabelledId 菜单项。

js
function updateMenuItem(linkHostname) {
  browser.menus.update(openLabelledId, {
    title: `Open (${linkHostname})`,
  });
  browser.menus.refresh();
}

browser.menus.onShown.addListener((info) => {
  if (!info.linkUrl) {
    return;
  }
  let linkElement = document.createElement("a");
  linkElement.href = info.linkUrl;
  updateMenuItem(linkElement.hostname);
});

扩展程序示例

浏览器兼容性