如何在本地存储中保存动态创建的元素
我有这个程序可以动态地制作带有内容的可折叠元素。我试图将创建的可折叠元素保存在本地存储中。我能够成功地将用户输入保存在本地存储中,但当我尝试将具有相同类名的元素保存在本地存储中时遇到了障碍。我尝试了这样的方法:
var collapsibles = document.getElementsByClassName('collapsible');
function populateStorage() {
localStorage.setItem('collapsibles', document.getElementsByClassName('collapsible'));
setStyles();
}
function setStyles() {
var collapsibles = localStorage.getItem('collapsibles');
document.getElementById("myCollapsibles").innerHTML = collapsibles;
}
collapsibles.onchange = populateStorage;
但是它没有起作用,是否可以将动态创建的元素保存在本地存储中?
程序代码片段(不包括本地存储片段):
var currentClosable;
var currentContent;
function selectedColl() {
document.getElementById("inputTaskDiv").style.display = "block";
currentClosable = event.target;
currentContent = currentClosable.nextElementSibling;
var inputTaskDiv = document.getElementById("inputTaskDiv");
$(currentContent).append(inputTaskDiv);
}
var taskCounter = 0;
function addTask() {
var text = document.getElementById("taskInput").value;
// create a new div element and give it a unique id
var newTask = $("<div class='currentTask'><input class='checkbox' type='checkbox'><label>" + text + "</label></div>");
newTask.id = 'temp' + taskCounter;
taskCounter++
// and give it some content
var newContent = document.createTextNode(text);
$(currentContent).append(newTask);
console.log("appended");
$(".currentTask").hover(
function() {
var taskCur = event.target;
$( this ).find( "a" ).last().remove();
$(taskCur).append( $( "<a class='taskX'> x</a>" ) );
function dump() {
$(taskCur).remove();
}
$( "a" ).on( "click", dump );
}, function() {
$( this ).find( "a" ).last().remove();
});
document.getElementById("taskInput").value = " ";
}
var elementCounter = 0;
var elementCounterContent = 0;
var text;
function addElement() {
text = document.getElementById("input").value;
// create a new div element and give it a unique id
var newDiv = $("<button class='collapsible' onclick='selectedColl()'></button>").text(text);
$(newDiv).append("<button class='btnDelete'>Delete</button>");
var newContentOfDiv = $("<div class='content'></div>");
newDiv.id = 'temp' + elementCounter;
newContentOfDiv.id = 'content' + elementCounterContent;
newDiv.classList = "div";
elementCounter++
elementCounterContent++
// and give it some content
var newContent = document.createTextNode(text);
// add the newly created element and its content into the DOM
document.getElementById("input").value = " ";
$("#divColl").append(newDiv, newContentOfDiv);
newDiv.click(function () {
this.classList.toggle("active");
content = this.nextElementSibling;
if (content.style.display === 'block') {
content.style.display = 'none';
} else {
content.style.display = 'block';
}
});
}
$("#divColl").on('click', '.btnDelete', function () {
$(this).closest('.collapsible').remove();
content.style.display = 'none';
});
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #555;
}
.collapsible:after {
content: '\002B';
color: white;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212";
}
.content {
padding: 0 18px;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.taskX{
color:red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<!---Add Step --->
<div id="addSteps">
<p>Make a collapsible:</p>
<input id="input" type="text" placeholder="title for collapsible"><button onclick="addElement()">Make</button>
</div>
<!-- Add tasks to steps --->
<div id="addTasksToSteps" style="display:none">
<div id="inputTaskDiv" style="display:none">
<input id="taskInput" type="text"><button onclick="addTask()">Add Task</button>
</div>
</div>
<!-- Final --->
<div id="scheduleDiv" style="display:none">
</div>
<div id="divColl"></div>
<header></header>
</body>
</html>
localStorage 需要字符串
您可以添加一个 span
var newDiv = $("<button class='collapsible'><span class='text'>"+text+"</span></button>");
也可以使用委托
$("#divColl").on("click","collapsible", selectedColl)
和
const arr = $("#divColl").find("button .text")
.map(function() { return this.textContent })
.get();
localStorage.setItem("arr",JSON.stringify(arr)); // stringify is mandatory for non-strings
既然有 jQuery,为什么还要将 DOM 访问混入其中?或者,如果您想使用 DOM 访问,为什么要使用 jQuery
var currentClosable;
var currentContent;
function selectedColl() {
document.getElementById("inputTaskDiv").style.display = "block";
currentClosable = event.target;
currentContent = currentClosable.nextElementSibling;
var inputTaskDiv = document.getElementById("inputTaskDiv");
$(currentContent).append(inputTaskDiv);
}
var taskCounter = 0;
function addTask() {
var text = document.getElementById("taskInput").value;
// create a new div element and give it a unique id
var newTask = $("<div class='currentTask'><input class='checkbox' type='checkbox'><label>" + text + "</label></div>");
newTask.id = 'temp' + taskCounter;
taskCounter++
// and give it some content
var newContent = document.createTextNode(text);
$(currentContent).append(newTask);
console.log("appended");
$(".currentTask").hover(
function() {
var taskCur = event.target;
$(this).find("a").last().remove();
$(taskCur).append($("<a class='taskX'> x</a>"));
function dump() {
$(taskCur).remove();
}
$("a").on("click", dump);
},
function() {
$(this).find("a").last().remove();
});
document.getElementById("taskInput").value = " ";
}
var elementCounter = 0;
var elementCounterContent = 0;
var text;
function addElement() {
text = document.getElementById("input").value;
// create a new div element and give it a unique id
var newDiv = $("<button class='collapsible'><span class='text'>"+text+"</span></button>");
$(newDiv).append("<button class='btnDelete'>Delete</button>");
var newContentOfDiv = $("<div class='content'></div>");
newDiv.id = 'temp' + elementCounter;
newContentOfDiv.id = 'content' + elementCounterContent;
newDiv.classList = "div";
elementCounter++
elementCounterContent++
// and give it some content
var newContent = document.createTextNode(text);
// add the newly created element and its content into the DOM
document.getElementById("input").value = " ";
$("#divColl").append(newDiv, newContentOfDiv);
// here store the content in localStorage
console.log($("#divColl").find("button .text").map(function() { return this.textContent }).get())
newDiv.click(function() {
this.classList.toggle("active");
content = this.nextElementSibling;
if (content.style.display === 'block') {
content.style.display = 'none';
} else {
content.style.display = 'block';
}
});
}
$("#divColl").on('click', '.btnDelete', function() {
$(this).closest('.collapsible').remove();
content.style.display = 'none';
});
$("#divColl").on("click","collapsible", selectedColl)
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #555;
}
.collapsible:after {
content: '\002B';
color: white;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212";
}
.content {
padding: 0 18px;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.taskX {
color: red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Project HOB</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<!---Add Step --->
<div id="addSteps">
<p>Make a collapsible:</p>
<input id="input" type="text" placeholder="title for collapsible"><button onclick="addElement()">Make</button>
</div>
<!-- Add tasks to steps --->
<div id="addTasksToSteps" style="display:none">
<div id="inputTaskDiv" style="display:none">
<input id="taskInput" type="text"><button onclick="addTask()">Add Task</button>
</div>
</div>
<!-- Final Schedule --->
<div id="scheduleDiv" style="display:none">
</div>
<div id="divColl">
<h1 id="assignmentTitle"></h1>
</div>
<div class="container"></div>
<header></header>
<script src="script.js"></script>
</body>
</html>
为了获得更好的最终结果,请尝试将表示逻辑与数据逻辑分开。因此,与其将整个 HTML 存储到本地存储中,为什么不创建一个包含任务的数据结构,然后对该数据结构进行更改并将其存储到本地存储中呢?当您加载页面时,您会从存储中获取数据并将其呈现到您的页面。这种分离将使您的应用程序易于维护和更改。
如果我是您,我可以建议您使用这个数据结构:
[
{
title: "Task group title",
tasks: [{
status: "done",
title: "Task title"
}]
}
]
这将使您完全控制您的项目,并且以后扩展起来会更容易。因为当您在设计中更改某些内容时,存储表示层将花费您很多钱。当然在这种情况下,使用 Vuejs 或 React 等框架会更容易……
但对于您当前的问题:
document.getElementsByClassName
将返回一个 HTML 对象数组,并且它不能直接作为字符串存储在本地存储中,您必须存储 HTML 字符串。本地存储只能存储字符串
有关 localStorage 的更多信息,请访问: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
所以你需要对它们进行迭代并获取它们的 HTML。或者您可以使用它们的容器,只需通过 ID 获取其内容并存储其 innerHTML 并在需要时检索它
如果您在带有 i 的循环中使用以下代码,则将是:
localStorage.setItem('collapsibles', document.getElementsByClassName('collapsible')[i].outerHTML);
所以基本上您可以使用:
localStorage.setItem('collapsibles', document.getElementById('divColl').innerHTML);
然后在需要时设置 divColl 的 innerHTML。像
document.getElementById('divColl').innerHTML = localStorage.getItem('collapsibles')
通过这种方式,您将整个 HTML 存储到本地存储中。而不仅仅是将存储的对象:“[object HTMLDivElement]”