我基本上建立了一个非常简单的列表。在顶部的输入字段中写入内容,单击按钮,它将显示在下方的ul中。
我在我的控制台中遇到两个错误,我不确定我做错了什么。
首先,在第12行,这个事件监听器:
deleteBtn.addEventListener('click', removeItem);
错误显示“无法读取属性'addEventListener'为null”并且我认为这是因为deleteBtn不在加载页面上,当您向列表添加项目时,它将添加到带有li的DOM中。
其次,在第40行:
selectedItem.removeChild(checkMark);
错误显示“无法在'节点'上执行'removeChild':要删除的节点不是此节点的子节点。”
这是我的所有代码:
<!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>Bootstrap Crash Course</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css"
integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb"
crossorigin="anonymous" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
crossorigin="anonymous">
<style type="text/css">
#myButton {
cursor: pointer;
}
.input-group {
margin: 15px 0;
}
.fa-times-circle-o {
font-size: 24px;
cursor: pointer;
}
.fa-check-circle {
font-size: 24px;
}
</style>
</head>
<body>
<div class="container">
<div class="input-group">
<input type="text" class="rounded form-control" id="myInput" />
<span id="myButton" class="input-group-addon">Click</span>
</div>
<ul class="list-group" id="myOutput">
</ul>
</div> <!-- .containter -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"
integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"
integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ"
crossorigin="anonymous"></script>
<script src="app.js"></script>
</body>
</html>
//Code from app.js
let myButton = document.getElementById('myButton');
let myOutput = document.getElementById('myOutput');
let myInput = document.getElementById('myInput');
let listGroupItems = document.querySelectorAll('.list-group-item');
let deleteBtn = document.getElementById('deleteBtn');
setUpEventListeners();
function setUpEventListeners() {
myButton.addEventListener('click', addItem);
myOutput.addEventListener('click', toggleItem);
deleteBtn.addEventListener('click', removeItem);
}
function addItem() {
if (myInput.value === '') {
console.log('Field is empty!');
} else {
let li = document.createElement('li');
let inputValue = document.createTextNode(myInput.value);
li.innerHTML = '<i class="fa fa-times-circle-o float-right" aria-hidden="true" id="deleteBtn"></i>';
li.className = 'list-group-item';
myOutput.appendChild(li);
li.appendChild(inputValue);
}
myInput.value = '';
}
function toggleItem(e) {
let selectedItem = e.target;
let checkMark = document.createElement('i');
checkMark.classList.add('fa', 'fa-check-circle', 'float-left');
console.log(selectedItem);
if (selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
selectedItem.classList.remove('bg-success');
selectedItem.classList.remove('text-white');
//listGroupItems.removeChild(checkMark);
} else if (!selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
selectedItem.classList.add('bg-success');
selectedItem.classList.add('text-white');
selectedItem.appendChild(checkMark);
}
}
function removeItem() {
e.target.parentElement.remove();
}
不是在创建之前向deleteBtn
添加事件,而是在创建按钮时使用onclick
添加内联事件并调用函数removeItem
并使用this
传递上下文
对于第二个问题,listGroupItems
是一个数组。所以数组中没有removeChild
方法。
要解决第二个问题,请从childNodes
集合中获取图标的索引。然后使用该索引删除此特定子项
let myButton = document.getElementById('myButton');
let myOutput = document.getElementById('myOutput');
let myInput = document.getElementById('myInput');
let listGroupItems = document.querySelectorAll('.list-group-item');
setUpEventListeners();
function setUpEventListeners() {
myButton.addEventListener('click', addItem);
myOutput.addEventListener('click', toggleItem);
}
function addItem() {
if (myInput.value === '') {
console.log('Field is empty!');
} else {
let li = document.createElement('li');
let inputValue = document.createTextNode(myInput.value);
// Changed here adding onclick
li.innerHTML = '<i class="fa fa-times-circle-o float-right" aria-hidden="true" onclick="removeItem(this)" class="deleteBtn"></i>';
li.className = 'list-group-item';
myOutput.appendChild(li);
li.appendChild(inputValue);
}
myInput.value = '';
}
function toggleItem(e) {
let selectedItem = e.target;
if (selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
selectedItem.classList.remove('bg-success');
selectedItem.classList.remove('text-white');
var iconIndex = '';
// getting the index of the icon which have the specifc class from childNodes using its class
for (var i = 0; i < selectedItem.childNodes.length; i++) {
if (selectedItem.childNodes[i].className === "fa fa-check-circle float-left") {
iconIndex = i;
}
}
// Using that index to remove the icon child
selectedItem.removeChild(selectedItem.childNodes[iconIndex]);
} else if (!selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
let checkMark = document.createElement('i');
checkMark.classList.add('fa', 'fa-check-circle', 'float-left');
selectedItem.classList.add('bg-success');
selectedItem.classList.add('text-white');
selectedItem.appendChild(checkMark);
}
}
function removeItem(elem) {
elem.parentNode.remove();
}
#myButton {
cursor: pointer;
}
.input-group {
margin: 15px 0;
}
.fa-times-circle-o {
font-size: 24px;
cursor: pointer;
}
.fa-check-circle {
font-size: 24px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous" />
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
<div class="container">
<div class="input-group">
<input type="text" class="rounded form-control" id="myInput" />
<span id="myButton" class="input-group-addon">Click</span>
</div>
<ul class="list-group" id="myOutput">
</ul>
</div>
deleteBtn变量是未定义的,因为您在页面加载时没有至少一个id为deleteBtn的项目。
要使用removeChild()
方法删除元素,签名是:
parentOfTarget.removeChild(target)
在下面的演示中,Template Literals和insertAdjacentHTML()
用于合并元素创建和插入DOM。顺便说一下,你不能为多次创建的元素分配一个id。 ids是独特的,所以#deleteBtn
被删除。如果你还是delegate events,按钮上不需要id。
有大量的课程上下班,所以我把它们放在数组中,然后在forEach()
的每次迭代中切换每个类
详情在演示中评论
var xBtn = document.getElementById('xButton');
var xOut = document.getElementById('xOutput');
var xInp = document.getElementById('xInput');
xBtn.addEventListener('click', addItem);
xOut.addEventListener('click', iconClick);
function addItem() {
if (xInp.value === '') {
console.log('Field is empty!');
} else {
/* This is a Template Literal which is a string
|| with powerful syntax and methods
*/
let li = `<li class='list-group-item'>
<i class="fa fa-circle-o float-left"></i>
${xInp.value}
<i class="fa fa-times-circle-o float-right"></i>
</li>`;
// Use insertAdjacentHTML() instead of innerHTML
xOut.insertAdjacentHTML('beforeend', li);
}
xInp.value = '';
}
function iconClick(e) {
// Reference e.target
var tgt = e.target;
// Reference e.target's parent
var item = tgt.parentElement;
/* if e.target has class .float-left
|| forEach() will...
*/
if (tgt.classList.contains('float-left')) {
// toggle e.target's FA icon classes
['fa-check-circle', 'fa-circle-o'].forEach(function(c, idx) {
tgt.classList.toggle(c);
});
// toggle e.target's parent's state classes
['bg-success', 'text-white'].forEach(function(i, idx) {
item.classList.toggle(i);
});
/* ...but if it has class .float-right
|| remove the parent of e.target by referencing
|| the parent of the parent of e.target (grandma)
*/
} else if (tgt.classList.contains('float-right')) {
xOut.removeChild(item);
// ...otherwise just end function
} else {
return false;
}
}
<!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>Bootstrap Crash Course</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<style>
#xButton {
cursor: pointer;
}
.input-group {
margin: 15px 0;
}
.fa {
font-size: 24px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<div class="input-group">
<input type="text" class="rounded form-control" id="xInput" />
<button id="xButton" class="btn btn-primary input-group-addon">ADD</button>
</div>
<ul class="list-group" id="xOutput">
</ul>
</div>
<!-- .containter -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"></script>
</body>
</html>