Javascript 使用<;表格>;在选项页面中&;browser.storage.local.get()在内容脚本中不起作用

Javascript 使用<;表格>;在选项页面中&;browser.storage.local.get()在内容脚本中不起作用,javascript,firefox,firefox-addon,firefox-addon-webextensions,Javascript,Firefox,Firefox Addon,Firefox Addon Webextensions,我正在开发一个Firefox插件,用户可以在选项页面上设置一些值。当用户访问站点时,将执行内容脚本,然后需要读取前面在“选项”页面上设置的值 我遵循了MDN指南“”中“添加设置”标题下的每一步,并使用给定的示例代码创建了所有文件。虽然设置、更改和读取选项页面上的值工作正常,但在内容脚本文件(在指南中名为borderify.js)中,我无法执行相同的操作。在指南的具体代码示例中,无论选项页面上设置了什么,它始终使用默认的蓝色边框 我查看了内容脚本的wiki页面,但它只是说:“除了标准的domapi

我正在开发一个Firefox插件,用户可以在选项页面上设置一些值。当用户访问站点时,将执行内容脚本,然后需要读取前面在“选项”页面上设置的值

我遵循了MDN指南“”中“添加设置”标题下的每一步,并使用给定的示例代码创建了所有文件。虽然设置、更改和读取选项页面上的值工作正常,但在内容脚本文件(在指南中名为borderify.js)中,我无法执行相同的操作。在指南的具体代码示例中,无论选项页面上设置了什么,它始终使用默认的蓝色边框

我查看了内容脚本的wiki页面,但它只是说:“除了标准的domapi之外,内容脚本还可以使用以下webextensionapi:[…]存储中的所有内容。”

所有这些都通过全新的Firefox配置文件和版本50.0.2进行了测试

有人能帮我解决这个问题吗

manifest.json

{

  "manifest_version": 2,
  "name": "Settings example",
  "version": "1.0",

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["borderify.js"]
    }
  ],

  "applications": {
    "gecko": {
      "id": "settings-example@mozilla.org"
    }
  },

  "options_ui": {
    "page": "options.html"
  },

  "permissions": ["storage"]

}
borderify.js

function onError(error) {
  console.log(`Error: ${error}`);
}

function onGot(item) {
  var color = "blue";
  if (item.color) {
    color = item.color;
  }
  document.body.style.border = "10px solid " + color;
}

var getting = browser.storage.local.get("color");
getting.then(onGot, onError);

有两个问题阻止此代码工作:

  • Firefox 52之前版本中的一个bug,当内容脚本中履行了来自
    browser.storage.local.get()
    的承诺时,会返回一个对象数组。这个承诺应该用一个目标来实现
  • 在选项页中使用
    提交
    事件,而不在事件处理程序中执行
    preventDefault()
  • Firefox版本<52时出现Firefox错误 在内容脚本中,当
    browser.storage.local.get()
    的承诺实现时,您将收到一个由一个对象而不是一个对象组成的数组。数组中的对象正确地具有
    color
    属性。如果使用与options.js中的
    browser.storage.local.get()
    相同的代码,则可以正确地获取对象。在FirefoxDeveloperEdition(52.0a2)和Nightly(53.0a1)中,对象被正确接收

    使用chrome.storage.local.get()
    API可以在所有情况下正确返回对象。我建议使用此API而不是
    browser.storage.local.get()

    如果决定继续使用
    browser.storage.local.get()
    ,则需要说明当前在Firefox<52中获取对象数组(在
    项[0]
    中具有正确的对象)以及在Firefox>=52中正确获取对象的情况

    在选项页中使用
    submit
    事件的
    需要
    preventDefault()
    这是MDN页“”上的代码中的一个问题。我已经更新了该页面上的代码,以反映下面描述的问题

    问题在于,您在options.html和options.js中使用了
    事件的
    submit
    ,而没有阻止默认操作

    如果不阻止默认操作,Firefox将尝试将页面提交到原始URL。在选项页面上,这显然是失败的。但是,它的失败会导致Firefox重新加载选项页面。这会破坏选项页以前存在的作用域,导致对
    storage.local.set()
    的调用在实际设置值之前中止
    storage.local.set()
    是异步的,因此它在中止之前启动,但不足以实际更改StorageArea中的值

    如果您添加
    e.preventDefault(),您的扩展将起作用
    到options.js中的
    saveOptions()
    ,如下所示:

    函数保存选项(e){
    e、 预防默认值();
    browser.storage.local.set({
    颜色:document.querySelector(“#color”).value
    });
    }
    
    注意:说Firefox的“最新版本”对我们没有帮助。请具体说明,如果没有其他原因,这个问题将存在数年,那么即使我们假设你指的是Firefox主发布版本,人们也不会知道你指的是什么版本。此外,Firefox总是有很多版本,包括但不限于:、Firefox Nightly、Firefox Beta、Firefox Unbranded Beta、Firefox Unbranded Release,以及大多数人使用的:Firefox(标准版)。对不起,版本是50.0.2。我还将在问题中添加示例文件的代码。在(OSX上的Ctrl-Shift-J或Cmd-Shift-J)中到底显示了什么当您尝试安装和使用扩展时?更改选项后是否重新加载网页?我重新加载了测试站点并打开了新站点,但它们都显示了蓝色边框,尽管我在“设置”页面中将值更改为红色并单击了“保存”。控制台没有输出任何与插件相关的内容,但是当我添加console.log(item.color)时;在borderify.js中onGot函数的开头,控制台中的输出未定义。感谢您的回答。您的解释和解决方案非常合理,但不幸的是,即使添加了“e.preventDefault();”项,item.color仍然没有定义。我用新的Firefox配置文件(我把它作为一个临时插件加载)和几个不同的站点对它进行了测试。我错过什么了吗?再次感谢您抽出时间。@J.Doe,我可以重新测试。然而,在发布这个答案之前,我做了一个测试。在Firefox 50.0.2和Firefox开发者版(52.0a2)中,我首先复制了这个问题——在这两个版本中,都是为了确定问题的起因——使用直接从您的问题中复制的代码。然后我测试了这个解决方案(两个方面)。通过上面的更改,边框的颜色确实发生了更改,以匹配选项中设置的颜色(一旦重新加载网页)。确定。我现在看到的另一个问题似乎与正在使用的Firefox版本有关。我还在调查。好吧,我刚刚做了一个新的测试:我把问题中完全相同的代码复制到新文件中,下载了Firefox 50.0.2 fr
    function saveOptions(e) {
      browser.storage.local.set({
        color: document.querySelector("#color").value
      });
    }
    
    function restoreOptions() {
    
      function setCurrentChoice(result) {
        document.querySelector("#color").value = result.color || "blue";
      }
    
      function onError(error) {
        console.log(`Error: ${error}`);
      }
    
      var getting = browser.storage.local.get("color");
      getting.then(setCurrentChoice, onError);
    }
    
    document.addEventListener("DOMContentLoaded", restoreOptions);
    document.querySelector("form").addEventListener("submit", saveOptions);
    
    function onError(error) {
      console.log(`Error: ${error}`);
    }
    
    function onGot(item) {
      var color = "blue";
      if (item.color) {
        color = item.color;
      }
      document.body.style.border = "10px solid " + color;
    }
    
    var getting = browser.storage.local.get("color");
    getting.then(onGot, onError);