localStorage保存HTML克隆

localStorage save HTML Clone

本文关键字:克隆 HTML 保存 localStorage      更新时间:2023-09-26

我想使用localStorage来保存一个包含HTML克隆的对象。

var myObject["test"] = document.getElementByID("someElement").cloneNode(true);
myObject["test2"] = document.getElementByID("someOtherElement").cloneNode(true);
localStorage.saveObject = JSON.stringify(myObject);

但是Object saveObject仍然等于{}。看来,字符串化不能对HTML节点进行字符串化,如果我碰巧以任何方式解决了保存它的问题,有可能将这个对象解析回HTML节点吗?

有人知道解决方案吗?

您的节点引用将从字符串化对象中删除,因为根据定义,JSON不能包含函数或节点引用,只能包含基元或子数组/对象。换句话说,您无法在本地存储中保留对节点的引用。相反,您需要通过ID、类或其他方式记录对它们的引用。

[编辑,以回应OP的评论]

JSON和JS对象不是一回事。前者源于后者,但它们并不相同。JSON是一种存储方式,因此不能包含对任何动态内容的引用。HTML元素不是永久存在的;它们作为运行时(DOM)概念存在,一旦页面离开,这些概念就会消失。因此,它们不能以任何有意义的方式存储。

因此,JSON只能存储原始数据——字符串、数字和布尔值——以及允许嵌套的结构——数组和子JSON定义。

因此,当您在对象上运行stringify时,不合适的部分会被剥离。在您的情况下,这是两种属性。因此,您需要以一种更永久、可重新访问的格式存储对元素的引用——通过ID或类,或其他提醒机制。

var obj = {el1: '#some_element', el2: '.some_other_element'};
localStorage.saveObject = JSON.stringify(obj);

在那里,我将我的两个元素保存为对它们的ID(第一个)和类(第二个)的引用。

然后,当您重新加载本地存储时,您可以根据这些因素查找元素,例如,将它们提供给jQuery选择器。

一个解决方法是:

  1. 获取要克隆的节点的outerHTML
  2. 将outerHTML(字符串)存储在本地存储中
  3. 加载时创建一个新元素,并将其附加到文档中
  4. 将保存在本地存储中的outerHTML分配给新元素

快速示例:

window.saveArray = new Array();
var clone = document.getElementByID("someElement").cloneNode(true);
saveArray.push(clone.outerHTML);
function save(){
    localStorage["elements"] = JSON.stringify(saveArray);
}
function load(){
    var tempsave = JSON.parse(localStorage["elements"]);
    for (var i = 0; i < tempsave.length; i++){      
        var element = document.createElement('div');
        document.getElementById('element-container').appendChild(element); 
        element.outerHTML = tempsave[i];    
    }
}
要将HTML节点保存为字符串,可以使用XMLSerializer。
var node = document.getElementByID("elementID");
var serializer = new XMLSerializer();
var htmlStr = serializer.serializeToString(node);
localStorage.setItem("saved", htmlStr);

现在您可以将其设置为节点的innerHTML。

document.getElementById("elementContainerID").innerHTML = localStorage.getItem("saved");

注意!如果要复制已被赋予新值的输入元素,则不会保存这些输入元素。因为节点将使用值属性inputElement.getAttribute("value")而不是新的给定属性inputElement.value进行复制。要解决此问题,可以在序列化节点之前将所有输入值复制到value属性。

document.querySelectorAll("input").forEach((el) => el.setAttribute("value", el.value));