【问题标题】:Struggling to determine how to store and retrieve JSON using drop down menus努力确定如何使用下拉菜单存储和检索 JSON
【发布时间】:2016-04-29 16:40:29
【问题描述】:

我正在创建一个 chrome 扩展,其中包含 JSON 格式的信息

options.js:

 var data = {
  "websites" : [
  {
    id: 1,
    'baseURL': 'http://www.monoprice.com/search/index?keyword=',
    'spaceValue': '+',
    'img': 'monoprice.png',
    'name': 'Monoprice'
  },
  {
    id: 2,
    'baseURL': 'https://www.youtube.com/results?search_query=',
    'spaceValue': '+',
    'img': 'youtube.png',
    'name': 'Youtube'
  },
  {
    id: 3,
    'baseURL': 'http://www.amazon.com/s/field-keywords=',
    'spaceValue': '%20',
    'img': 'amazon.png',
    'name': 'Amazon'
  },
  {
    id: 4,
    'baseURL': 'http://stackoverflow.com/search?q=',
    'spaceValue': '+',
    'img': 'stack.png',
    'name': 'Stack'
  }
  ]
};

function save_options() {
  var itemOne = document.getElementById('1').value;
  var itemTwo = document.getElementById('2').value;
  var itemThree = document.getElementById('3').value;
  var itemFour = document.getElementById('4').value;

  chrome.storage.sync.set({
    'One': itemOne,
    'Two': itemTwo,
    'Three': itemThree,
    'Four': itemFour,
  }, function() {
    // Update status to let user know options were saved.
    var status = document.getElementById('status');
    status.textContent = 'Options saved.';
    setTimeout(function() {
      status.textContent = '';
    }, 750);
  });
}


// Restores select box and checkbox state using the preferences
// stored in chrome.storage.
function restore_options() {
  // Use default value color = 'red' and likesColor = true.
  chrome.storage.sync.get({
    "One": "none",
    "Two": "none",
    "Three": "none",
    "Four": "none",
  }, function(items) {
    document.getElementById('1').value = items.One;
    document.getElementById('2').value = items.Two;
    document.getElementById('3').value = items.Three;
    document.getElementById('4').value = items.Four;
  });
}
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click', save_options);

有了这些信息,我希望用户选择将此信息应用于实际 chrome 扩展的顺序。

扩展图片:

我在 options.html 页面中使用下拉菜单:

options.html:

<!DOCTYPE html>
<html>
<head><title>My Test Extension Options</title></head>
<body>
<select id="1">
  <option value="">None</option>
  <option value="amazon">Amazon</option>
  <option value="youtube">Youtube</option>
  <option value="monoprice">Monoprice</option>
  <option value="stack">Stack</option>

</select>

<select id="2">
  <option value="">None</option>
  <option value="amazon">Amazon</option>
  <option value="youtube">Youtube</option>
  <option value="monoprice">Monoprice</option>
  <option value="stack">Stack</option>

</select>
<select id="3">
  <option value="">None</option>
  <option value="amazon">Amazon</option>
  <option value="youtube">Youtube</option>
  <option value="monoprice">Monoprice</option>
  <option value="stack">Stack</option>

</select>
<select id="4">
  <option value="">None</option>
  <option value="amazon">Amazon</option>
  <option value="youtube">Youtube</option>
  <option value="monoprice">Monoprice</option>
  <option value="stack">Stack</option>

</select>

<div id="status"></div>
<button id="save">Save</button>

<script src="options.js"></script>
</body>
</html>

但我不知道如何以编程方式链接所选下拉菜单和 JSON 数组,然后使用 chrome.storage.sync.set({}); 存储和调用该数据

谢谢!

我知道这可能会造成混淆,我很乐意提供任何所需的说明。

【问题讨论】:

  • 您对哪个部分有问题?或者更确切地说,你可以自己做哪些部分?你能提供一些带有“这里我不知道该怎么做”部分的骨架代码吗?
  • @Xan 我已使用完整代码(options.html 和 options.js)编辑了帖子。因为它可以保存和存储下拉值,但正如您所见,它很丑陋且不可扩展。我想知道如何使用下拉列表中的值来引用,然后正确保存和恢复 JSON 数据。
  • 此时基本上是数据组织问题。它澄清了你的问题,谢谢。

标签: javascript html json google-chrome-extension


【解决方案1】:

因此,您已经有了用于将值保存/加载到存储的有效、正确的代码。这是一个使用有效数据并改善用户(和程序员!)体验的问题。

让我们看看您在此处遇到的使访问数据变得尴尬的问题:

  1. 您存储来自value 属性的标识符,但这些标识符(还)对您的数据结构没有任何意义。另一方面,您的数据中有 id 字段,您无论如何都不会使用。

    结论:两者使用相同的标识符。它建立了相关性。

  2. 您在数据中的唯一标识符是数字,但它们是手工编码的。如果数据有意义,维护数据可能会更容易,并且这还允许您重新排序数据而不会失去 ID 的顺序感。

    结论:使用唯一但有意义的标识符,就像你已经用于value 的标识符。

  3. 您将数据组织在一个数组中,但它的预期用途是通过标识符查找它。这是低效的:您必须遍历数组,直到找到标识符。一个对象解决了这个问题:它直接将标识符映射到数据。

    数组很容易添加,但您仍然需要一个唯一标识符(通过添加/删除数据保持不变),这样就抵消了优势。

    结论:不要使用包含 id/value 对的数组,使用将 id 映射到值的对象。

    将三个放在一起:

    websites: {
      amazon: {
        baseURL: 'http://www.amazon.com/s/field-keywords=',
        spaceValue: '%20',
        img: 'amazon.png',
        name: 'Amazon'
      },
      // ...
    ]
    

    (请注意,在 JS 代码中,不需要引用对象标识符,当然也不应该将它们混合在一起,但是如果将其存储在单独的 JSON 文件中,则需要引用它们)

现在您可以通过存储在存储中的 ID 访问所需的任何属性:例如,data.websites[id].name


我们可以在这里完成,但让我们让程序员(你的!)以后的生活更轻松。

  1. 假设您要添加一个新网站。您不仅必须将其添加到data,这当然是必需的,而且您还需要在整个页面上复制粘贴一个新的&lt;option&gt;。或者,如果您更改网站的名称,则需要在任何地方对其进行修补。这是应该避免的事情,并且通过动态生成&lt;option&gt;s 来自动化并不难。

    让我们修改你的 HTML:

    <select class="website-select" id="1"></select>
    <!-- ... -->
    <select class="website-select" id="4"></select>
    

    现在让我们填充它:

    // Assumes Chrome 45+ for newer JS things
    var selects = Array.from(document.getElementsByClassName('website-select'));
    for (var select of selects) {
      var noneOption = document.createElement('option');
      noneOption.value = '';
      noneOption.text = 'None';
      select.appendChild(noneOption);
      for (id in data.websites) {
        var websiteOption = document.createElement('option');
        websiteOption.value = id;
        websiteOption.text = data.websites[id].name;
        select.appendChild(websiteOption);
      }
    }
    
  2. 原则上,这同样适用于&lt;select&gt;s 本身。如果您想允许它们的数量可变,或者只是稍后更改数量怎么办?数据的 ID("One""Two"、...)也需要硬编码且不可扩展。

    也许最好在存储中保存一个数组,并在此基础上构建整个界面。访问已保存的首选项也将变得更加容易。

    留给读者作为练习

  3. 如果您修改您的data.websites,您保存的id 可能会失效——它不再映射到任何网站。这会导致引用data.websites[id] 的代码失败。

    虽然可以添加检查它是否存在于任何地方,但最好验证您的数据一次(或者如果您添加该功能,则尽可能频繁地验证您的 data.websites),然后依赖于它是有效的事实。

    这是一个示例验证:

    function validate(callback) {
      var defaults = {
        "One": "",
        "Two": "",
        "Three": "",
        "Four": "",
      };        
    
      chrome.storage.sync.get(defaults, function(items) {
        for (var option in items) {
          if (items[option] && !data.websites[items[option]]) {
            // Reset invalid data
            items[option] = "";
          }
        }
        chrome.storage.sync.set(items, callback);
      });
    }
    
  4. 您可能希望通过不要求用户单击“保存”来改善用户体验。它涉及将您的保存逻辑绑定到&lt;select&gt; 元素的change 事件上的事件,而不是保存上的click

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 1970-01-01
    相关资源
    最近更新 更多