开发者问题收集

如何在本地存储中保存动态创建的元素

2020-12-21
2120

我有这个程序可以动态地制作带有内容的可折叠元素。我试图将创建的可折叠元素保存在本地存储中。我能够成功地将用户输入保存在本地存储中,但当我尝试将具有相同类名的元素保存在本地存储中时遇到了障碍。我尝试了这样的方法:

   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>
2个回答

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>
mplungjan
2020-12-21

为了获得更好的最终结果,请尝试将表示逻辑与数据逻辑分开。因此,与其将整个 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]”

HSLM
2020-12-21