在 DOM 中移动元素时,该元素是否保持状态
when moving element in DOM, does that element remain state?
<ul id="task1">
<li><input type="checkbox" id="input1"><label>Item task1></label></li>
... some other <li> go here
</ul>
<ul id="task2">
<li><input type="checkbox"><label>Item task2></label></li>
...
</ul>
var task1 = document.getElementById("task1");
var task2 = document.getElementById("task2");
var moveFromTask1to2 = function() { task2.appendChild(this.parentNode); }
var moveFromTask2to1 = function() { task1.appendChild(this.parentNode); }
var bindElement(listItem, task) {
var checkbox = listItem.querySelector("input[type=checkbox]");
checkbox.onchange = task;
}
for (var i = 0; i < task1.children.length; i++) { bindElement(task1.children[i], moveFromTask1to2); //(1)
for (var i = 0; i < task2.children.length; i++) { bindElement(task2.children[i], moveFromTask2to1); //(2)
当我选中input1
复选框时,它应该从task1
移动到task2
。它做到了。
但是当我再次选中input1
复选框时,它不会从task2
移回task1
谁能告诉我为什么?
问题是第一个列表#task1
中的复选框#task2
更改事件时移动到列表中。发生这种情况后,在后续更改事件中,复选框仍会移动到同一列表中,因为事件处理程序是相同的。这就是您无法将复选框移回初始列表的原因。
要修复它,您可以编写一个函数而不是两个moveFromTask1to2
和moveFromTask2to1
。例如:
var moveFromTo = function() {
var moveTo = this.parentNode.parentNode === task1 ? task2 : task1;
moveTo.appendChild(this.parentNode);
};
查看下面的演示。
var task1 = document.getElementById("task1");
var task2 = document.getElementById("task2");
var moveFromTo = function() {
var moveTo = this.parentNode.parentNode === task1 ? task2 : task1;
moveTo.appendChild(this.parentNode);
}
var bindElement = function(listItem, task) {
var checkbox = listItem.querySelector("input[type=checkbox]");
checkbox.onchange = task;
}
for (var i = 0; i < task1.children.length; i++) { bindElement(task1.children[i], moveFromTo); } //(1)
for (var i = 0; i < task2.children.length; i++) { bindElement(task2.children[i], moveFromTo); } //(2)
<ul id="task1">
<li>
<input type="checkbox" id="input1" />
<label>Item task11></label>
</li>
<li>
<input type="checkbox" id="input1" />
<label>Item task12></label>
</li>
</ul>
<ul id="task2">
<li>
<input type="checkbox" />
<label>Item task21></label>
</li>
<li>
<input type="checkbox" />
<label>Item task22></label>
</li>
</ul>
您将事件处理程序绑定到名为 moveFromTask1to2
的对象。
您的任何代码都不会删除该事件处理程序并添加moveFromTask2to1
。
JavaScript不会进行时间旅行。它不会撤消您的for
循环所执行的操作并重新运行它们,因为它们过去运行的数据从那时起发生了变化。
您可能应该通过使用单个事件处理程序函数来解决此问题,该函数不是硬编码 from 和 to 元素,而是根据 this.parentNode
的值计算它们。
问题是,当您单击复选框时,事件不会自动更改。它仍然具有相同的事件处理程序,这会将其从任务 1 移动到任务 2。
解决方案 1:在移动后分配新的事件处理程序:
var moveFromTask1to2 = function() {
task2.appendChild(this.parentNode);
this.onchange = moveFromTask2to1;
}
var moveFromTask2to1 = function() {
task1.appendChild(this.parentNode);
this.onchange = moveFromTask1to2;
}
解决方案 2:使事件处理程序更通用,使其成为单个"切换"函数:
var task1 = document.getElementById("task1");
var task2 = document.getElementById("task2");
var moveItem = function() {
var task = this.parentNode.parentNode;
if (task == task1)
task2.appendChild(this.parentNode);
else
task1.appendChild(this.parentNode);
}
var bindElement = function(listItem) {
var checkbox = listItem.querySelector("input[type=checkbox]");
checkbox.onchange = moveItem;
}
for (var i = 0; i < task1.children.length; i++) { bindElement(task1.children[i]);} //(1)
for (var i = 0; i < task2.children.length; i++) { bindElement(task2.children[i]);} //(2)
ul {
border: 1px solid blue;
}
<ul id="task1">
<li><input type="checkbox" id="input1"><label>Item task1></label></li>
</ul>
<ul id="task2">
<li><input type="checkbox"><label>Item task2></label></li>
...
</ul>
不过,您会注意到,移动有效,但复选框会记住状态(即"选中"(。您可能会在代码中重置它,但实际上我认为从 UX 的角度来看,这是一个非常糟糕的解决方案。复选框用于检查/选择元素。它不应该做任何事情。如果希望能够将列表项移动到另一个列表,则应改用按钮。
不过,这并不能改变答案。如果将复选框更改为按钮并使用 onclick 事件而不是 onchange,则相同的答案适用。从技术上讲,它与上面的代码片段几乎相同,但从用户的角度来看,这更有意义:
var task1 = document.getElementById("task1");
var task2 = document.getElementById("task2");
var moveItem = function() {
var task = this.parentNode.parentNode;
if (task == task1)
task2.appendChild(this.parentNode);
else
task1.appendChild(this.parentNode);
}
var bindElement = function(listItem) {
var button = listItem.querySelector("input[type=button]");
button.onclick = moveItem;
}
for (var i = 0; i < task1.children.length; i++) { bindElement(task1.children[i]);} //(1)
for (var i = 0; i < task2.children.length; i++) { bindElement(task2.children[i]);} //(2)
ul {
border: 1px solid blue;
}
<ul id="task1">
<li><input type="button" value="Move"/><label>Item task1></label></li>
</ul>
<ul id="task2">
<li><input type="button" value="Move"><label>Item task2></label></li>
...
</ul>
- javascript数组元素是否知道其封闭数组
- 如何检查元素是否在iframe中
- 检查元素是否将状态从隐藏更改为可见
- 确定元素是否存在
- 消隐数组元素是否生成自己的属性
- 检查一个元素是否有一个类与另一个类总是返回true
- 如何检查日期选择器和时间选择器元素是否使用JQuery/Javascript设置
- 如何查找具有该ID的元素是否存在
- 检查元素是否已单击或hasClass
- 使用webdriver和selenium验证元素是否不存在
- 如何使用jQuery实时检查元素是否为空
- html元素是否具有内置的属性
- 检查元素是否有内容
- 使用 javascript 检查元素是否包含子标记而不是文本
- JavaScript 在 JSON 对象中移动如何判断元素是否存在
- 检查两个或多个 DOM 元素是否重叠
- 谷歌地球插件 — 如何检查带有 ID 的元素是否已经存在
- 检查元素是否悬停在上面
- DOM 元素是否可以具有其值为任意对象(而不是字符串)的属性
- 如何检查DOM元素是否已完全加载