我的代码在下面的jsfiddle代码段中。每当我按下“删除”按钮时,都需要2次单击才能删除最初用html生成的框。如果我添加了它们,则这些框一键即可正常工作。问题在于这些通过标记制作的盒子。
链接到代码:this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box-container {
display: flex;
}
.box-item {
display: inline-block;
height: 30px;
width: 30px;
background: orangered;
margin: 0 10px;
}
.activated {
background: dodgerblue;
}
</style>
</head>
<body>
<div id="box-container">
<span class="1 box-item"></span>
<span class="2 box-item"></span>
<span class="3 box-item"></span>
</div>
<button id="add">Add</button>
<button id="remove">Remove</button>
<script src="main.js"></script>
</body>
</html>
JS代码
const boxContainer = document.getElementById("box-container");
const boxItems = document.getElementsByClassName("box-item");
const addBtn = document.getElementById("add");
const removeBtn = document.getElementById("remove");
function Box(element) {
this.__el = element;
this.activated = true;
}
Box.prototype.init = function() {
this.activateBox();
this.__el.addEventListener("click", this.toggleActivation.bind(this));
};
Box.prototype.logger = function() {
console.log(this);
};
Box.prototype.activateBox = function() {
if (this.activated) {
this.__el.classList.add("activated");
}
};
Box.prototype.deactivateBox = function() {
if (!this.activated) {
this.__el.classList.remove("activated");
}
};
Box.prototype.toggleActivation = function() {
this.__el.classList.toggle("activated");
return (this.activated = !this.activated);
};
let box = [];
for (let i = 0; i < boxItems.length; i++) {
box[i] = new Box(boxItems[i]);
box[i].init();
}
const addBox = function() {
const node = document.createElement("span");
node.classList.add("box-item", "activated");
boxContainer.appendChild(node);
};
function removeBox() {
boxContainer.removeChild(boxContainer.lastChild);
}
addBtn.addEventListener("click", addBox);
removeBtn.addEventListener("click", removeBox);
PS:我检查了其他两个标题相同的问题,但它们不能解决我的问题。
答案 0 :(得分:3)
问题是您的HTML在.box-item
之间包含文本节点:
<div id="box-container">
<span class="1 box-item"></span>
<span class="2 box-item"></span>
<span class="3 box-item"></span>
</div>
所以,当您致电
boxContainer.removeChild(boxContainer.lastChild);
如果父级的最后一个子节点是文本节点,则在使用lastChild
时将选择该文本节点。那不是您想要的-您不想选择文本节点。您只想删除<span>
元素,因此您可以删除.children
中的最后一项:
const { children } = boxContainer;
boxContainer.removeChild(children[children.length - 1]);
或者,更优雅地,选择lastElementChild
属性,这要感谢Andre的评论:
boxContainer.removeChild(boxContainer.lastElementChild);
(令人困惑的是,children
的最终索引与lastChild
返回的节点不是相同)
const boxContainer = document.getElementById("box-container");
const boxItems = document.getElementsByClassName("box-item");
const addBtn = document.getElementById("add");
const removeBtn = document.getElementById("remove");
function Box(element) {
this.__el = element;
this.activated = true;
}
Box.prototype.init = function() {
this.activateBox();
this.__el.addEventListener("click", this.toggleActivation.bind(this));
};
Box.prototype.logger = function() {
console.log(this);
};
Box.prototype.activateBox = function() {
if (this.activated) {
this.__el.classList.add("activated");
}
};
Box.prototype.deactivateBox = function() {
if (!this.activated) {
this.__el.classList.remove("activated");
}
};
Box.prototype.toggleActivation = function() {
this.__el.classList.toggle("activated");
return (this.activated = !this.activated);
};
let box = [];
for (let i = 0; i < boxItems.length; i++) {
box[i] = new Box(boxItems[i]);
box[i].init();
}
const addBox = function() {
const node = document.createElement("span");
node.classList.add("box-item", "activated");
boxContainer.appendChild(node);
};
function removeBox() {
boxContainer.removeChild(boxContainer.lastElementChild);
}
addBtn.addEventListener("click", addBox);
removeBtn.addEventListener("click", removeBox);
.box-container {
display: flex;
}
.box-item {
display: inline-block;
height: 30px;
width: 30px;
background: orangered;
margin: 0 10px;
}
.activated {
background: dodgerblue;
}
<div id="box-container">
<span class="1 box-item"></span>
<span class="2 box-item"></span>
<span class="3 box-item"></span>
</div>
<button id="add">Add</button>
<button id="remove">Remove</button>
或者,您可以更改HTML以使没有文本节点:
<div id="box-container"><span class="1 box-item"></span><span class="2 box-item"></span><span class="3 box-item"></span></div>
const boxContainer = document.getElementById("box-container");
const boxItems = document.getElementsByClassName("box-item");
const addBtn = document.getElementById("add");
const removeBtn = document.getElementById("remove");
function Box(element) {
this.__el = element;
this.activated = true;
}
Box.prototype.init = function() {
this.activateBox();
this.__el.addEventListener("click", this.toggleActivation.bind(this));
};
Box.prototype.logger = function() {
console.log(this);
};
Box.prototype.activateBox = function() {
if (this.activated) {
this.__el.classList.add("activated");
}
};
Box.prototype.deactivateBox = function() {
if (!this.activated) {
this.__el.classList.remove("activated");
}
};
Box.prototype.toggleActivation = function() {
this.__el.classList.toggle("activated");
return (this.activated = !this.activated);
};
let box = [];
for (let i = 0; i < boxItems.length; i++) {
box[i] = new Box(boxItems[i]);
box[i].init();
}
const addBox = function() {
const node = document.createElement("span");
node.classList.add("box-item", "activated");
boxContainer.appendChild(node);
};
function removeBox() {
boxContainer.removeChild(boxContainer.lastChild);
}
addBtn.addEventListener("click", addBox);
removeBtn.addEventListener("click", removeBox);
.box-container {
display: flex;
}
.box-item {
display: inline-block;
height: 30px;
width: 30px;
background: orangered;
margin: 0 10px;
}
.activated {
background: dodgerblue;
}
<div id="box-container"><span class="1 box-item"></span><span class="2 box-item"></span><span class="3 box-item"></span></div>
<button id="add">Add</button>
<button id="remove">Remove</button>