【问题标题】:Can't apply checkbox properties to for loop无法将复选框属性应用于 for 循环
【发布时间】:2019-02-15 18:05:13
【问题描述】:

好吧,我希望我只是错过了一些简单的事情。基本上我正在制作一个待办事项列表,我希望每个列表项都出现一个复选框(这有效)。当用户单击复选框时, textDecoration = "line-through" 应该通过 listItem 类。这意味着一条线贯穿了该人创建的待办事项。这是我主要使用的代码:

function show() {
var todos = get_todos();

var html = '<ul>';
for(var i=0; i < todos.length; i++) {
    html += '<span><li class="listItem" style="float:left;">' + todos[i] + '</li><input class="checkBox" type="checkbox">' + '<button class="remove" id="' + i  + '"><i class="fa fa-trash" aria-hidden="true"></i></button></span><br/>';
};
html += '</ul>';

document.getElementById('todos').innerHTML = html;

var buttons = document.getElementsByClassName('remove');
for (var i=0; i < buttons.length; i++) {
    buttons[i].addEventListener('click', remove);
};

////////////////////////////////////
//Everything above here works. Below is the checkbox issue

var checkBox = document.getElementsByClassName("checkBox");
var listItem = document.getElementsByClassName("listItem");

for (var i=0; i < checkBox.length; i++) {
    if (checkBox.checked == true){
        listItem.style.textDecoration = "line-through";
    }else {
        listItem.style.textDecoration = "none";
    }
};}

我现在的情况是,如果我在原始复选框中创建一个 onClick 函数,我可以使用该 if/else 语句并且它有点工作。如果我使用 document.getElementsByClassName 设置 checkBox/listItems 变量,它将不起作用,但如果我使用 document.getElementById,它将起作用。问题是它只适用于用户创建的第一个任务,而没有其他任务。我假设这是因为 Id 仅适用于一个元素(与适用于多个元素的类不同),或者因为它不像上面的代码那样循环通过 for 循环。

TL/DR 基本上,当我运行上面的代码时,我不断收到“Uncaught TypeError: Cannot set property 'textDecoration' of undefined 在展会上 (todo.js:57) 在 todo.js:75"。

当我为复选框创建一个单独的函数并使用 elementbyid 而不是 elementsbyclass 时,我没有收到此错误(也更改了上面 html 部分的 id/class)

我真的想让这些直通效果适用于所有任务,而不仅仅是第一个任务。任何想法都非常感谢。谢谢大家!

【问题讨论】:

  • 您必须使用 checkBox[i] 并找到合适的 listItem[i] 来设置 textDecoration,目前您正在检查整个列表(checkBox)
  • listItem是元素集合,style不是元素集合的属性,所以style是undefined,所以不能在上面设置textDecoration。您必须遍历每个 listItem 元素才能以这种方式设置属性。 (同样适用于checkBox(它是一个集合))
  • 因此,当我尝试按照var checkBoxes = document.getElementsByClassName("checkBox"); var listItems = document.getElementsByClassName("listItem"); for (var i=0; i &lt; checkBoxes.length; i++) { if (checkBoxes[i].checked == true){ listItems[i].style.textDecoration = "line-through"; }else { listItems[i].style.textDecoration = "none"; } };} 的方式进行操作时,我没有收到任何控制台错误,但单击该复选框时不会执行任何操作。有什么想法吗?

标签: javascript for-loop if-statement


【解决方案1】:

我会用 css 而不是 javascript 来完成这个(如果可能的话,这通常是我的规则)。在这种情况下,你必须对你的标记做一个小改动:因为没有previous-sibling选择器,你必须把inputs放在相应的lis之前,但是因为lis是@ 987654328@ 它仍然呈现完全相同的效果。

input:checked + li {
  text-decoration:line-through;
}
<ul>
<span><input class="checkBox" type="checkbox"><li class="listItem" style="float:left;">foo</li><button class="remove" id="' + i  + '"><i class="fa fa-trash" aria-hidden="true"></i></button></span><br/>
<span><input class="checkBox" type="checkbox"><li class="listItem" style="float:left;">bar</li><button class="remove" id="' + i  + '"><i class="fa fa-trash" aria-hidden="true"></i></button></span><br/>
<span><input class="checkBox" type="checkbox"><li class="listItem" style="float:left;">baz</li><button class="remove" id="' + i  + '"><i class="fa fa-trash" aria-hidden="true"></i></button></span><br/>
</ul>

【讨论】:

  • 老实说,这是完美的。我开始尝试在 javascript 中执行此操作,但 css 要简单得多。这确实做得很好,我认为我离兔子洞太远了,没有注意到 css 可以让这更容易。非常感谢你们和大家的努力!
  • 如果它是有效的 HTML,那么它可能被认为是完美的;但由于 &lt;ul&gt;&lt;ol&gt; 的唯一有效子元素是 &lt;li&gt; 元素(不,&lt;div&gt;&lt;span&gt;&lt;a&gt; 元素是 not 有效子元素)然后换行您希望 strike-through 在容器元素(在 &lt;li&gt; 内)中作为 &lt;input&gt; 的相邻兄弟的内容:&lt;li&gt;&lt;input type="checkbox"&gt;&lt;div&gt;&lt;!-- other contents --&gt;&lt;/div&gt;&lt;/li&gt;
【解决方案2】:

function show() {
  var todos = get_todos();

  var html = '<ul>';
  for (var i = 0; i < todos.length; i++) {
    html += '<span><li class="listItem" style="float:left;">' + todos[i] + '</li><input class="checkBox" type="checkbox">' + '<button class="remove" id="' + i + '"><i class="fa fa-trash" aria-hidden="true"></i></button></span><br/>';
  };
  html += '</ul>';

  document.getElementById('todos').innerHTML = html;

  var buttons = document.getElementsByClassName('remove');
  for (var i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener('click', remove);
  };

  ////////////////////////////////////
  //Everything above here works. Below is the checkbox issue

  var checkBox = document.getElementsByClassName("checkBox");
  var listItem = document.getElementsByClassName("listItem");

  for (var i = 0; i < checkBox.length; i++) {
    if (checkBox[i].checked == true) {
      listItem[i].style.textDecoration = "line-through";
    } else {
      listItem[i].style.textDecoration = "none";
    }
  };
}

您可能错过了 listItem 和 checkBox 数组中的索引

【讨论】:

  • 嗯,所以当我这样做时,我没有收到任何控制台错误,但是当我单击复选框时没有任何反应。
【解决方案3】:

我认为问题在于checkBox 是一个类似数组的对象。我想您知道,当您编写代码时,您会查看 checkBox.length,但是您无法索引到数组中。

你有:

var checkBox = document.getElementsByClassName("checkBox");
var listItem = document.getElementsByClassName("listItem");

for (var i=0; i < checkBox.length; i++) {
    if (checkBox.checked == true){
        listItem.style.textDecoration = "line-through";
    }else {
        listItem.style.textDecoration = "none";
    }
};}

为了清楚起见,我在需要的地方使用了复数形式的名称,并添加了索引参考:

var checkBoxes = document.getElementsByClassName("checkBox");
var listItems = document.getElementsByClassName("listItem");

for (var i=0; i < checkBoxes.length; i++) {
    if (checkBoxes[i].checked == true){
        listItems[i].style.textDecoration = "line-through";
    }else {
        listItems[i].style.textDecoration = "none";
    }
};}

【讨论】:

  • 好的,当我尝试将您的代码与索引引用一起使用时,我没有任何控制台错误。但是,当我单击复选框时没有任何反应。
  • 您的代码在代码运行时设置列表项的属性。它不会创建任何类型的永久绑定。您需要在复选框上添加一个事件,然后触发上面的代码。如果您最终需要做很多这样的事情,那么您可能会考虑使用框架、Vuejs、React 或类似的(有很多,但现在可能是最流行的两个)来为您处理此类绑定。
猜你喜欢
  • 2019-02-24
  • 2018-02-24
  • 2014-05-06
  • 2020-08-25
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-11
相关资源
最近更新 更多