当前位置: 首页 > 面试题库 >

在新标签/窗口中传递数据或修改扩展名html

阚小云
2023-03-14
问题内容

我正在尝试将DOM附加到从打开的自我chrome扩展文件中popup.js。假设我在chrome扩展文件中存在一个名为的文件temp.html,在执行时的某个时刻popup.js,我使用打开了该文件,chrome.tabs.create然后将DOM附加到此html文件中。

无论如何,我可以从那里开始popup.js吗?

Extension files:

1-manifest.json
2-functions
    functions.js
    domToTables.js
3-libs
    jquery-3.3.1.min.js
    bootstrap-4.2.1-dist
4-myTables
    stylesheet.css
    *temp.html* \\this file
5-popup
    stylesheet.css
    index.html
    popup.js
6-background.js
7-content.js

问题答案:

尽管您可以使用chrome.extension.getViews直接访问在新标签页/窗口中打开的扩展页面的DOM(或者直接访问,如果使用window.open),但这是一种非常round回的方法,并且在使用时从browser_action弹出窗口中,将需要在后台(active:false在chrome.tabs.create的参数中)打开选项卡,这是不可靠的,因为另一个扩展名可能会强制激活选项卡,从而关闭browser_action弹出窗口并立即终止其脚本。

一种简单/正确的方法是将数据传递到另一个页面,并通过标准通过HTML加载到该页面html中的脚本中处理数据<script src="other-page.js"></script>

1.通过HTML5 localStorage共享+同步访问

如果您需要在加载第一页画框之前在另一页内访问数据,请使用此选项,例如选择浅色/深色主题。您必须使用JSON’格式化非字符串类型,例如对象或数组。

劣势:如果您'storage'在扩展程序的其他页面中观察到DOM 事件,则可能会很慢。

popup.js:

localStorage.sharedData = JSON.stringify({foo: 123, bar: [1, 2, 3], theme: 'dark'});
chrome.tabs.create({url: 'other-page.html'});

other-page.js:

let sharedData;
try {
  sharedData = JSON.parse(localStorage.sharedData);
  if (sharedData.theme === 'dark') {
    document.documentElement.style = 'background: #000; color: #aaa;';
  }
} catch (e) {}
delete localStorage.sharedData;

2.通过URL参数共享+同步访问

如果您需要在加载第一页画框之前在另一页内访问数据,请使用此选项,例如选择浅色/深色主题。您必须使用JSON’格式化非字符串类型,例如对象或数组。

缺点:地址栏中的网址太长。

popup.js:

chrome.tabs.create({
  url: 'other-page.html?data=' + encodeURIComponent(JSON.stringify({foo: [1, 2, 3]})),
});

other-page.js:

let sharedData;
try {
  sharedData = JSON.parse(new URLSearchParams(location.search).get('data'));
} catch (e) {}
// simplify the displayed URL in the address bar
history.replace({}, document.title, location.origin + location.pathname);

3.通过后台页面共享全局变量+同步访问

如果您需要在加载第一页画框之前在另一页内访问数据,请使用此选项,例如选择浅色/深色主题。您必须使用JSON’格式化非字符串类型,例如对象或数组。

缺点1:需要后台页面。

劣势2:需要使用JSON’ification或自定义的deepClone来深克隆对象,该对象对于跨窗口上下文可以正常工作(AFAIK并不流行的deepClone会实现此条件),特别是它应该使用目标窗口的引用对象构造函数。

manifest.json:

"background": {
  "scripts": ["bg.js"],
  "persistent": false
}

popup.js:

// ensure the non-persistent background page is loaded
chrome.runtime.getBackgroundPage(bg => {
  // using JSON'ification to avoid dead cross-window references.
  bg.sharedData = JSON.stringify({foo: 123, bar: [1, 2, 3], theme: 'dark'});
  chrome.tabs.create({url: 'other-page.html'});
});

other-page.js:

// if this tab was reloaded the background page may be unloaded and the variable is lost
// but we were saving a copy in HTML5 sessionStorage!
let sharedData = sessionStorage.sharedData;
if (!sharedData) {
  const bg = chrome.extension.getBackgroundPage();
  sharedData = bg && bg.sharedData;
  if (sharedData) {
    sessionStorage.sharedData = sharedData;
  }
}
// using JSON'ification to avoid dead cross-window references.
try {
  sharedData = JSON.parse(sharedData);
} catch (e) {}

4.两步通过后台页面消息共享

如果您需要在后台页面中执行一系列操作(仅打开第一步),请使用此选项。例如,我们需要在第二步中传递数据。

需要背景页面,因为当在显示弹出窗口的同一窗口中打开活动选项卡时,弹出窗口将关闭并且其脚本将不再运行。可能有人认为,使用选项卡创建active: false将解决问题,但仅在用户决定安装另一种覆盖选项卡打开行为的扩展名之前才可以解决。您可能会认为您可以打开一个新窗口,但同样不能保证其他扩展程序不会将新窗口的选项卡重新附加到现有窗口中,从而关闭弹出窗口。

缺点1:在Chrome中,数据内部经过JSON’格式化,因此它使所有非标准类型(如WeakMap,TypedArray,Blob等)都受到干扰。在Firefox中,它们似乎正在使用结构化克隆,因此可以共享更多类型。

缺点2:我们两次发送相同的数据消息。

注意:我正在使用Mozilla的WebExtensionpolyfill。

manifest.json:

"background": {
  "scripts": [
    "browser-polyfill.min.js",
    "bg.js"
  ],
  "persistent": false
}

popup.js:

chrome.runtime.sendMessage({
  action: 'openTab',
  url: '/other-page.html',
  data: {foo: 123, bar: [1, 2, 3], theme: 'dark'},
});

bg.js:

function onTabLoaded(tabId) {
  return new Promise(resolve => {
    browser.tabs.onUpdated.addListener(function onUpdated(id, change) {
      if (id === tabId && change.status === 'complete') {
        browser.tabs.onUpdated.removeListener(onUpdated);
        resolve();
      }
    });
  });
}

browser.runtime.onMessage.addListener(async (msg = {}, sender) => {
  if (msg.action === 'openTab') {
    const tab = await browser.tabs.create({url: msg.url});
    await onTabLoaded(tab.id);
    await browser.tabs.sendMessage(tab.id, {
      action: 'setData',
      data: msg.data,
    });
  }
});

other-page.html:

<!doctype html>
<p id="text"></p>
<!-- scripts at the end of the page run when DOM is ready -->
<script src="other-page.js"></script>

other-page.js:

chrome.runtime.onMessage.addListener((msg, sender) => {
  if (msg.action === 'setData') {
    console.log(msg.data);
    document.getElementById('text').textContent = JSON.stringify(msg.data, null, '  ');
    // you can use msg.data only inside this callback
    // and you can save it in a global variable to use in the code 
    // that's guaranteed to run at a later point in time
  }
});

5.通过chrome.storage.local分享



 类似资料:
  • 我正在创建一个safari扩展。如何手动将新选项卡/窗口设置为我选择的URL?我使用了这篇文章中的一些逻辑来确保我只是接管了用户创建的选项卡/WindowsSafariExtension:Event来创建一个全新的选项卡? 我设置了我的新选项卡事件侦听器: 使用此选项处理打开的选项卡/窗口: 当一个新的选项卡/窗口打开时,我能够发出警报,但我一辈子都不知道如何浏览到url。我尝试了window.l

  • 问题内容: 是否可以在新标签页而不是同一标签页中打开链接? 问题答案: 您应该在锚标记中添加和。 例如: 添加不是强制性的,但这是建议的安全措施。可以在下面的链接中找到更多信息。

  • 我是一个使用Scenebuilder和MVC初学者的新javaFx。 我有一个问题如下:我试图制作一个主窗口来提醒一个新窗口。我试图在警报窗口中对标签文本进行MIDI。但我不能那样做。我得到了这个错误: 我有一个带有maincontroller、alertController和main的主窗口。fxml和警报。fxml如下所示: 主要内容: 主控制器: 主要的fxml: AlertControll

  • 问题 你需要向C库函数传递文件名,但是需要确保文件名根据系统期望的文件名编码方式编码过。 解决方案 写一个接受一个文件名为参数的扩展函数,如下这样: static PyObject *py_get_filename(PyObject *self, PyObject *args) { PyObject *bytes; char *filename; Py_ssize_t len; i

  • 问题内容: 我想通过目录递归迭代和修改某一分机的所有文件的扩展名,说来。bash命令执行此操作是什么? 问题答案: 如果您有可用的重命名,请使用: 如果重命名不可用,请使用:

  • 用于打开url或载入url至 BrowserWindow ,并对该窗口进行少量功能的控制. 使用 window.open 创建一个新窗口时,会自动创建一个 BrowserWindowProxy 的实例将返回一个标识,可通过标识对这个新窗口进行少量功能的控制. 不过希望完全的控制这个窗口,请直接创建一个 BrowserWindow .新创建的 BrowserWindow 默认为继承父窗口的属性参数,