猿问

更改数组元素值的样式

我正在构建一个待办事项列表,但无法弄清楚如何保留具有直通装饰的数组值。调用 render 方法时,数组就会从头开始构建。意味着如果我删除一个 li,则所有其他已由复选框标记为直通的 li,都会丢失装饰。我该怎么做才能保持线路畅通?到目前为止,我尝试在 markTask 方法中将原始值替换为带有直通线的值,但它不起作用。基本上,我试图完成的是通过插入带有直通式的值,以便能够检查该值是否具有直通式样式,并且在渲染之后能够将选中的复选框保持为选中状态。


到目前为止我的代码:


class Todo {

  constructor() {

    this.input = document.getElementById("input");

    this.ul = document.getElementById("ul");

    this.form = document.getElementById("form");

    this.tasks = [];

    this.registerEvent();

  }


  registerEvent() {

    this.form.addEventListener("submit", (event) => {

      event.preventDefault();

      this.createTask(this.input.value);

      this.form.reset();

    });

  }


  createTask(task) {

    if (task.trim().length === 0) {

      return;

    }

    this.tasks.push(task);

    this.render();

  }


  deleteTask(task) {

    const myTask = task.target;

    const parent = myTask.parentNode;

    const taskToRemove = parent.childNodes[1].textContent;

    const index = this.tasks.indexOf(taskToRemove);

    this.tasks.splice(index, 1);

    this.render();

  }


  markTask(task) {

    const myTask = task.target;

    const parent = myTask.parentNode;

    

    if (myTask.checked) {

      parent.style.textDecoration = "line-through";

    } else {

      parent.style.textDecoration = "none";

    }

  }


  render() {

    this.ul.innerHTML = "";

    this.tasks.forEach((task) => {

      const li = document.createElement("li");

      const cb = document.createElement("input");

      cb.type = "checkbox";

      cb.addEventListener("click", (e) => {

        this.markTask(e);

      });

      li.appendChild(cb);


      li.append(document.createTextNode(task));


      const btn = document.createElement("button");

      li.appendChild(btn);

      btn.textContent = "Delete";

      btn.classList.add("remove");

      btn.addEventListener("click", (e) => {

        this.deleteTask(e);

      });

      this.ul.appendChild(li);

    });

  }

}


new Todo();

<form id="form">

  <input id="input" />

  <button id="add">Add</button>

</form>

<ul id="ul">

  

</ul>


慕标5832272
浏览 121回答 3
3回答

子衿沉夜

这是因为你没有跟踪哪些任务已完成,而只是在推动字符串。对于您的createTask方法,您需要推送一个具有完成属性的对象来指示哪些任务已完成,如下所示&nbsp;createTask(task) {&nbsp;if (task.trim().length === 0) {&nbsp; return;&nbsp;}&nbsp;this.tasks.push({title: task, done: false});&nbsp;this.render();&nbsp;}更新渲染以考虑已完成的任务render() {this.ul.innerHTML = "";this.tasks.forEach((task) => {&nbsp; const li = document.createElement("li");&nbsp; const cb = document.createElement("input");&nbsp; cb.type = "checkbox";&nbsp; cb.addEventListener("click", (e) => {&nbsp; &nbsp; this.markTask(e);&nbsp; });&nbsp; li.appendChild(cb);&nbsp; li.append(document.createTextNode(task.title));&nbsp; const btn = document.createElement("button");&nbsp; li.appendChild(btn);&nbsp; btn.textContent = "Delete";&nbsp; btn.classList.add("remove");&nbsp; btn.addEventListener("click", (e) => {&nbsp; &nbsp; this.deleteTask(e);&nbsp; });&nbsp; this.ul.appendChild(li);&nbsp; &nbsp;if (task.done) {&nbsp; &nbsp; cb.checked = true;&nbsp; &nbsp; li.style.textDecoration = "line-through";&nbsp; &nbsp;} else {&nbsp; &nbsp; cb.checked = false;&nbsp; &nbsp; li.style.textDecoration = "none";&nbsp; &nbsp;}&nbsp;});}在你的构造函数中更新你的任务变量以查看其效果constructor() {this.input = document.getElementById("input");this.ul = document.getElementById("ul");this.form = document.getElementById("form");this.tasks = [{title: 'mill', done: true}, {title: 'jus', done: false}];this.registerEvent();}希望您能了解总体思路。我不会完成整个实现,markTask因为这应该足以让您了解解决方案应该是什么。祝你好运。

临摹微笑

如果可以的话,我对你的代码做了一些修改。您需要的技术是事件委托:对子元素的任何单击也是对其父元素的单击。我们在父元素上放置事件侦听器,然后查看它发生在哪个子元素上。就您而言,这只会为您的所有“删除”按钮创建一个事件侦听器。另一个想法是不要忽略 DOM,它还保留任务列表,您不需要将它们保存在内存中的表中,这是多余的。这是代码:css也是有帮助的class Todo&nbsp;&nbsp; {&nbsp; constructor()&nbsp; &nbsp; {&nbsp; &nbsp; this.form&nbsp; = document.getElementById('todo-form')&nbsp; &nbsp; this.liste = document.getElementById('todo-list')&nbsp; &nbsp; this.form.onsubmit = e => this.addTask(e)&nbsp; &nbsp; this.liste.onclick = e => this.delTask(e)&nbsp; &nbsp; }&nbsp; addTask(e)&nbsp; &nbsp; {&nbsp; &nbsp; e.preventDefault()&nbsp; &nbsp; if (this.form.task.value.trim() === '') return&nbsp; &nbsp; let li = document.createElement('li')&nbsp; &nbsp; &nbsp; , cb = document.createElement('input')&nbsp; &nbsp; &nbsp; , sp = document.createElement('span')&nbsp; &nbsp; &nbsp; , bt = document.createElement('button')&nbsp; &nbsp; &nbsp; ;&nbsp; &nbsp; cb.type&nbsp; &nbsp; &nbsp; &nbsp; = 'checkbox'&nbsp; &nbsp; sp.textContent = this.form.task.value&nbsp; &nbsp; bt.textContent = 'Delete'&nbsp; &nbsp; bt.className&nbsp; &nbsp;= 'remove'&nbsp; &nbsp; li.appendChild(cb)&nbsp; &nbsp; li.appendChild(sp)&nbsp; &nbsp; li.appendChild(bt)&nbsp; &nbsp; this.liste.appendChild(li)&nbsp; &nbsp; this.form.reset()&nbsp; &nbsp; }&nbsp; delTask(e)&nbsp; &nbsp; {&nbsp; &nbsp; if (!e.target.matches('button.remove')) return // reject others clicks&nbsp; &nbsp; e.target.closest('li').remove()&nbsp; &nbsp; }&nbsp; }new Todo();#todo-list li > span {&nbsp; display&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : inline-block;&nbsp; background-color : whitesmoke;&nbsp; width&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : 20em;&nbsp; }#todo-list li input[type=checkbox]:checked + span {&nbsp; text-decoration : line-through;&nbsp; }#todo-list li button.remove {&nbsp; font-size: .6em;&nbsp; }<form id="todo-form">&nbsp; <input name="task">&nbsp; <button type="submit">Add</button></form><ul id="todo-list"></ul>正如您所看到的,这段代码更短。您还可以使用 IIFE 而不是类,如下所示:(function() // IIFE&nbsp; {&nbsp; let form&nbsp; = document.getElementById('todo-form')&nbsp; &nbsp; , liste = document.getElementById('todo-list')&nbsp; &nbsp; ;&nbsp; form.onsubmit = e =>&nbsp; // addTask&nbsp; &nbsp; {&nbsp; &nbsp; e.preventDefault()&nbsp; &nbsp; if (form.task.value.trim() === '') return&nbsp; &nbsp; let li = document.createElement('li')&nbsp; &nbsp; &nbsp; , cb = document.createElement('input')&nbsp; &nbsp; &nbsp; , sp = document.createElement('span')&nbsp; &nbsp; &nbsp; , bt = document.createElement('button')&nbsp; &nbsp; &nbsp; ;&nbsp; &nbsp; cb.type&nbsp; &nbsp; &nbsp; &nbsp; = 'checkbox'&nbsp; &nbsp; sp.textContent = form.task.value&nbsp; &nbsp; bt.textContent = 'Delete'&nbsp; &nbsp; bt.className&nbsp; &nbsp;= 'remove'&nbsp; &nbsp; li.appendChild(cb)&nbsp; &nbsp; li.appendChild(sp)&nbsp; &nbsp; li.appendChild(bt)&nbsp; &nbsp; liste.appendChild(li)&nbsp; &nbsp; form.reset()&nbsp; &nbsp; }&nbsp; liste.onclick = e =>&nbsp; // delTask&nbsp; &nbsp; {&nbsp; &nbsp; if (!e.target.matches('button.remove')) return // reject others clicks&nbsp; &nbsp; e.target.closest('li').remove()&nbsp; &nbsp; }&nbsp; })()btTaskList.onclick = e =>&nbsp; {&nbsp; let tasks = [...document.querySelectorAll('#todo-list li')].map(li=>&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; let val = li.querySelector('span').textContent&nbsp; &nbsp; &nbsp; , chk = li.querySelector('input[type=checkbox]').checked&nbsp; &nbsp; &nbsp; ;&nbsp; &nbsp; return {val,chk}&nbsp; &nbsp; })&nbsp; console.clear()&nbsp; console.log( tasks )&nbsp; }#todo-list li > span {&nbsp; display&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : inline-block;&nbsp; background-color : whitesmoke;&nbsp; width&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : 20em;&nbsp; }#todo-list li input[type=checkbox]:checked + span {&nbsp; text-decoration : line-through;&nbsp; }#todo-list li button.remove {&nbsp; font-size: .6em;&nbsp; }<form id="todo-form">&nbsp; <input name="task">&nbsp; <button type="submit">Add</button></form><ul id="todo-list"></ul>&nbsp;&nbsp;<button id="btTaskList">get task list</button>我还添加了一个get task list按钮...

慕森王

标记元素后,您仅更改元素的 Stayle 和属性。但是删除后,您会使用render整个列表重新创建,并且render您不会渲染checked参数。你的渲染应该是:&nbsp; render() {&nbsp; &nbsp; this.ul.innerHTML = "";&nbsp; &nbsp; this.tasks.forEach((task) => {&nbsp; &nbsp; &nbsp; const li = document.createElement("li");&nbsp; &nbsp; &nbsp; const cb = document.createElement("input");&nbsp; &nbsp; &nbsp; cb.type = "checkbox";&nbsp; &nbsp; &nbsp; cb.addEventListener("click", (e) => {&nbsp; &nbsp; &nbsp; &nbsp; this.markTask(e);&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; li.appendChild(cb);&nbsp; &nbsp; &nbsp; // missed rendering checked&nbsp; &nbsp; &nbsp; if (task.checked) {&nbsp; &nbsp; &nbsp; &nbsp; li.style.textDecoration = "line-through";&nbsp; &nbsp; &nbsp; &nbsp; cb.checked = 'checked';&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; li.append(document.createTextNode(task));&nbsp; &nbsp; &nbsp; const btn = document.createElement("button");&nbsp; &nbsp; &nbsp; li.appendChild(btn);&nbsp; &nbsp; &nbsp; btn.textContent = "Delete";&nbsp; &nbsp; &nbsp; btn.classList.add("remove");&nbsp; &nbsp; &nbsp; btn.addEventListener("click", (e) => {&nbsp; &nbsp; &nbsp; &nbsp; this.deleteTask(e);&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; this.ul.appendChild(li);&nbsp; &nbsp; });&nbsp; }
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答