为什么localStorage中存储的HTML在浏览器中调用显示时会发生变化?

Why does HTML stored in localStorage change when recalled and displayed in the browser?

抱歉,如果之前有人问过这个问题,我已经搜索过但找不到任何相关的内容...

我这里有一个非常简单的网站,它有 3 个按钮:

  1. 添加组件

  2. 保存当前状态

  3. 恢复保存的状态

添加组件 按钮完全符合我的要求,即创建一个新的简单 collapse item<div data-role="collapsible-set" class="flow" id="collapsibleComponent"></div> 个标签。

此外,保存当前状态 storeCurrentState(); 按钮似乎捕获了所需的代码 与正在显示的内容 相同(正确)。

然而,当我点击Restore Saved State按钮(运行 restorePriorState();方法)时,从localStorage读取并放入的代码返回页面与保存的代码不一致。结果,我最终得到了如下所示的嵌套折叠项目...

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>TutorialW3a</title>
        <link href="jquery-mobile/jquery.mobile.theme-1.3.0.min.css" rel="stylesheet" type="text/css" />
        <link href="jquery-mobile/jquery.mobile.structure-1.3.0.min.css" rel="stylesheet" type="text/css" />
        <script src="jquery-mobile/jquery-1.11.1.min.js"></script>
        <script src="jquery-mobile/jquery.mobile-1.3.0.min.js"></script>
    </head>
    <body>
        <div data-role="page" id="page">
            <div data-role="header">
                <h1>Header</h1>
            </div>
            <div data-role="content">
                <div data-role="collapsible-set" class="flow" id="collapsibleComponent">
                    <!--New collapsible divs go here-->
                </div>
            </div>
            <button onclick="addCollapsibleComponent()">Add component</button>
            <button onclick="storeCurrentState()">Save current state</button>
            <button onclick="restorePriorState()">Restore saved state</button>
            <div data-role="footer" data-position="fixed">
                <h4>Footer</h4>
            </div>
        </div>
    </body>
</html>
<script>
    //
    var collapsibleComponentContent = document.getElementById("collapsibleComponent");
    var collapsibleDiv;
    function addCollapsibleComponent() {
        //create div element
        collapsibleDiv = $('<div id="new" data-role="collapsible" data-collapsed="true"><h3>Heading</h3><p>Paragraph</p></div>"');
        //append new collapsible div to #collapsibleComponent
        $("#collapsibleComponent").append(collapsibleDiv);
        //collapse all collapsible divs
        $('div[data-role="collapsible"]').collapsible();
    }
    //
    function storeCurrentState() {
        collapsibleDiv = document.getElementById("new");
        localStorage.setItem("html_data", JSON.stringify(collapsibleComponentContent.innerHTML));
    }
    //
    function restorePriorState() {
        collapsibleComponentContent.innerHTML = JSON.parse(localStorage.getItem("html_data"));
        $("#new").collapsible();
    }
</script>

这是创建新的可折叠组件时生成的...

<div id="new" data-role="collapsible" data-collapsed="true" class="ui-collapsible ui-collapsible-inset ui-collapsible-collapsed">
<h3 class="ui-collapsible-heading ui-collapsible-heading-collapsed">
    <a href="#" class="ui-collapsible-heading-toggle ui-btn ui-btn-icon-left ui-btn-up-c" data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="plus" data-iconpos="left" data-theme="c"
        ><span class="ui-btn-inner"
            ><span class="ui-btn-text">Heading<span class="ui-collapsible-heading-status"> click to expand contents</span></span
            ><span class="ui-icon ui-icon-plus ui-icon-shadow">&nbsp;</span></span
        ></a
    >
</h3>
<div class="ui-collapsible-content ui-collapsible-content-collapsed" aria-hidden="true"><p>Paragraph</p></div>

这是我重新加载时创建的...

<h3 class="ui-collapsible-heading ui-collapsible-heading-collapsed">
<a href="#" class="ui-collapsible-heading-toggle ui-btn ui-btn-icon-left ui-btn-up-c" data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="plus" data-iconpos="left" data-theme="c"
    ><span class="ui-btn-inner"
        ><span class="ui-btn-text"
            ><a href="#" class="ui-collapsible-heading-toggle ui-btn ui-btn-icon-left ui-btn-up-c" data-corners="false" data-shadow="false" data-iconshadow="true" data-wrapperels="span" data-icon="plus" data-iconpos="left" data-theme="c"
                ><span class="ui-btn-inner"
                    ><span class="ui-btn-text">Heading<span class="ui-collapsible-heading-status"> click to expand contents</span></span
                    ><span class="ui-icon ui-icon-plus ui-icon-shadow">&nbsp;</span></span
                ></a
            ><span class="ui-collapsible-heading-status"> click to expand contents</span></span
        ><span class="ui-icon ui-icon-plus ui-icon-shadow">&nbsp;</span></span
    ></a
>

你问的是“为什么”,答案如下:

JQM 是一个混合的 JS/CSS 框架,即 widgets 由 JS 增强并由 CSS 设计样式。页面初始化后,框架通过添加一些嵌套元素(divspan)、pseudo-elements(图标) 和事件处理程序。

就是说,在您的代码中,您正在保存初始标记的 增强 版本以及 data-role 属性,但您仅保存 markup,这意味着您不会保存在小部件初始化期间由框架创建的 JS data。简而言之,您只节省了已经增强的小部件的一半。

下一次,框架将再次找到 data-role 属性,但不会找到关联的 data 对象,并且通过调用 $("#new").collapsible(); 您最终会得到 double-nested 标记。

更多信息:

您可以按如下方式查看 JQM 小部件对象:

$.data(document.getElementById("new"),"mobile-collapsible")

或:

$("#new").jqmData("mobile-collapsible")

您的任务有不止一种可能的解决方案。

也许您可以恢复最初的 un-enhanced 标记:

$("#collapsibleComponent :jqmData(role='collapsible')").collapsible("destroy");

并保存:

localStorage.setItem("html_data", JSON.stringify($("#collapsibleComponent").html()));

最后,你假设

to capture the required code identically to what's being displayed is correct

错了。