【问题标题】:JS data in localStorage only being kept in one key, value pairlocalStorage 中的 JS 数据只保存在一个键值对中
【发布时间】:2014-02-04 17:14:24
【问题描述】:

我正在尝试编写一个简单的应用程序以尝试了解 HTML5 的 localStorage。我(以为我)已经成功创建了一个表单来获取数据并将其存储在 localStorage 中(使用 JSON.stringify),然后将其显示在页面上(在 JSON.parse 之后)。然后,我继续讨论如何删除特定项目,并意识到我认为我存储数据不正确,因为我只有 1 个键值对,而我认为每个条目都应该有一个。所以调用 localStorage.removeItem(key) 只是删除了我所有的数据。我需要帮助整理如何单独存储每个条目,以便可以一个一个地删除它们。

html:

<form id="sme-submission" name="sme-submission">
    <ul class="no-list-style">
        <li>
        <h2>Add an SME</h2>
        </li>
        <li>
            <label for="firstname">First Name:</label><br />
            <input type="text" id="firstname"/>
        </li>
        <li>
            <label for="lastname">Last Name:</label><br />
            <input type="text" id="lastname"/>
        </li>
        <li>
            <label for="email">Email:</label><br />
            <input type="email" id="email"/>
        </li>
        <li>
            <label for="subject">Subject:</label><br />
            <input type="text" id="subject"/>
        </li>
        <li>
            <input type="submit" value="Save" id="btnSave" class="btn btn-success"/>
        </li>
    </ul>
</form>

<div id="list-display">

</div>

<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>

JS:

var rolodex = localStorage.getItem('rolodex'); //load stored data if there is any

window.onload = function() {
    rolodex = JSON.parse(rolodex);
    if(rolodex === null) { //if no data, initialize an empty array
        rolodex = [];
    } else {
    console.log(rolodex);
    }


    var btnSave = document.getElementById('btnSave');
    btnSave.addEventListener('click', Add, false);

    List();
};    

var Add = function() {
    var SME = JSON.stringify({
        firstname:document.getElementById('firstname').value,
        lastname:document.getElementById('lastname').value,
        email:document.getElementById('email').value,
        subject:document.getElementById('subject').value,

    });

    rolodex.push(SME);
    localStorage.setItem('rolodex', JSON.stringify(rolodex));

for (var key in SME) {
    var person = JSON.parse(SME[key]);
    var div = document.getElementById('list-display').lastChild;
    div.innerHTML = div.innerHTML + "<div class='sme-entry'><ul class='no-list-  style'><li><h3>"+person.subject+"<h3></li><li>"+person.firstname+" "+person.lastname+"</li><li>"+person.email+"</li></ul></div>";
}

alert("Saved");
};

var List = function() {
    for (var key in rolodex) {
    var person = JSON.parse(rolodex[key]);
    var div = document.getElementById('list-display');
    div.innerHTML = div.innerHTML + "<div class='sme-entry'><ul class='no-list-style'><li><h3>"+person.subject+"</h3></li><li>"+person.firstname+" "+person.lastname+"</li><li>"+person.email+"</li></ul></div>";
    }
};

var Remove = function() {

};

【问题讨论】:

    标签: javascript json html local-storage


    【解决方案1】:

    localStorage 的关键在于它进行键值存储。

    您给了它一个键 ("rolodex"),因此它都是一个值 JSON.stringify(rolodex);

    就持久性而言,您有两种选择; 选择哪一个并不重要,只要您清楚地了解它们的工作原理即可。

    首先,一两条基本规则:

    1. localStorage 只是键值,并且该值必须是字符串(或能够转换为字符串)。

    2. 如果您计划从存储到应用程序来回切换,则需要确保每次都从字符串转换为字符串。

    话虽如此,您的选择如下:

    1. 继续做你正在做的事情。现在,您的图表如下所示:
      [{ name : "Bob" }, { name : "Doug" }] // simplified
      因此,您知道获取整个事物的密钥,将其转换为对象数组并以这种方式处理它是相对简单的。
      好处:就进出存储而言,它很容易使用。
      缺点:如果它变得巨大,它可能会开始变慢,只有一个键,很容易出错并覆盖所有内容,您必须获取 所有 数据来更新一个电子邮件地址等...

    2. 为每个人生成一个唯一的 ID(可能是姓名+电子邮件+手机,或者完全随机无所谓)。
      将每个 ID 推送到rolodex
      使用他们的 ID 分别保存每个联系人。
      var id = abc123; contact.id = id; rolodex.push(id); localStorage.set(id, JSON.stringify(contact));

    优点: 现在,您有了自己更安全的对象。
    编辑和保存时,您只能访问完成工作所需的最低限度的内容。
    您仍然可以使用 rolodex 来“循环”您的联系人(通过 id)。

    缺点: 虽然访问一个人会更快,但您需要已经知道他们的 ID。
    要知道这一点,您可能需要打开 rolodex... ...很好... ...但要知道 哪个 ID 是正确的,您可能必须遍历 rolodex,抓住每个 ID,一次一个,按 ID 抓取每个人,并对其进行测试,直到找到您想要的...
    很多这样做的效率会降低。
    同时,如果您确实拥有别人给您的 ID,那么抓住合适的人会更快。按索引查找变得非常快,而非索引查找变得愚蠢缓慢。

    构建所有内容也更加复杂。
    这个例子可能不是特别难,但是如果你有不同的 ID 数组来构建不同类型的对象,并且这些不同的对象具有由 ID 引用的其他对象的属性,然后你将它们链接在一起......

    ...恭喜,您刚刚替换了一个关系数据库,使用数组/属性作为外键的连接表,同时将该管理的复杂性从 SQL 转移到 JS(可能更容易或更难,具体取决于熟练程度)。

    典型应用的理想答案可能在中间:
    保持一个有用对象的数组循环遍历(例如:first_name + last_name + id + email),同时将这些对象的较大版本保存在它们自己的键下(完整版,包括生日、最新合作伙伴的姓名等)将使您更快地找到“我认识的戴夫”或“我的家庭成员”的列表,而无需打开每个人的包装。

    当然,然后您需要在两个地方更新用户(尽管很少有合法的名称更改,因此您会非常安全,除非通过联姻将非易失性数据存储在多个位置)。

    另一个选项与此完全相同,但在内存加载的另一端,是在应用启动时解压缩所有内容
    解压您的数组,循环遍历,并为每个 ID,将 ID 替换为该 ID at 的完整对象。

    然后,对于该对象的每个属性,如果该属性是一个 ID,则获取该 ID 处的对象,然后附加它,等等...

    现在您的所有数据都在内存中,因此您无需再次访问存储空间,并且您所做的任何更改一次只会发生在一个对象上,因此您可以只保存对象(或子-objects) 需要保存。

    当然,这里的缺点是它的启动速度最慢,并且需要最多的内存(这已经不是什么大问题了,除非你希望它在几乎不支持 localStorage 的旧手机上运行得很快) .

    【讨论】:

    • 感谢您提供如此详细的解释,它非常有帮助!这个应用程序将保持很小,因为它仅供我个人使用和学习。我喜欢一开始就拆开所有东西的想法,因为它永远不会太多,而且会让其他事情变得更容易。但是,出于学习目的,我也可能克隆并尝试索引方法。再次感谢 Norguard!
    【解决方案2】:

    Localstorage 接受您提供的内容。在这种情况下,您给了它一个充满项目的数组,所以这就是它存储在一个键下的内容。您可以改为单独存储每个项目,但您需要自己跟踪它们的名称(例如,将 lastIndexUsed 也存储在本地存储中,然后存储 "rolodex" + lastIndexUsed 的密钥)。

    最好承认您正在存储整个数组,而不是删除它。重新加载数组,并从中删除您想要的任何单个项目,然后再次保存数组。

    【讨论】:

      猜你喜欢
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-05
      • 2012-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多