我如何使两个按钮具有相同的功能工作?



感谢您的宝贵时间。因为我已经添加了两个+按钮(运行代码并按下"添加表")。按钮),它所做的只是向第一个表添加两个新行,随后的按钮不起作用。我试过调用类,使用循环,并把代码放在它应该在的地方,但它仍然拒绝。下面是我的代码:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="WELPPproto.css">
</head>
<body>
<h1 style="font-family:verdana">Word List</h1>
<table id="list">
<tr>
<th scope="col">Word</th>
<th scope="col">English</th>
<th scope="col">Pronunciation</th>
<th scope="col"><button class="deletethismaybe" id="deletethismaybe" type="button" title="delete this table">X</button></th>
</tr>
<tfoot>
<tr>
<div class="boxy_gril">
<td><input type="text" id="w" class="w" required /></td>
<td><input type="text" id="m" class="m" required /></td>
<td><input type="text" id="p" class="p" /></td>
</div>
</tr>
<tr>
<td colspan="3"><div class="button_boi"><button type="button" class="button_boi" id="add">Enter</button>
</div></td>
</tr>
</tfoot>
</table>
<div id="ntable" class="ntable" >
<section>

</section>
</div>
<br>
<br>
<button class="button_gril" id="addtable">Add Table</button>
<script>
document.getElementById("addtable").onclick = function() {
let puttable = document.getElementById("ntable");
let section = puttable.querySelector('section');
let tableHTML = '<br><br>' + '<table id="list">' + '<tr>' +
'<th scope="col">' + 'Word' + '</td>' +
'<th scope="col">' + 'English' + '</th>' +
'<th scope="col">' + 'Pronunciation' + '</th>' + '<th><button class="deletethismaybe" id="deletethismaybe" type="button" title="delete this table">X</button></th>' + 
'</tr>' +
'<tfoot><tr><div class="boxy_gril">' + 
'<td><input type="text" id="w" class="w" required /></td>'+
'<td><input type="text" id="m" class="m" required />' + 
'</td><td><input type="text" id="p" class="p" /></td>' + 
'</div></tr>' + '<tr>' + '<td colspan="3">' + '<div class="button_boi">' + '<button type="button" class="button_boi" id="add">Enter</button>' + '</div>' + '</td>'+ '</tr>' + '</tfoot>' + '</table>';

section.insertAdjacentHTML('beforebegin', tableHTML);

}
document.addEventListener('click', (e) => {
let thatTarget = e.target;
let thatBtn = thatTarget.closest('.deletethismaybe');
if (thatBtn) {
e.preventDefault();
thatTarget.closest('table').remove();
thatTarget.closest('button').remove();
}
})
var asdf = document.getElementsByClassName("button_boi");
for (var i = 0; i < asdf.length; i++) {
asdf[i].onclick = function() {
let listTable = document.getElementById("list");
let tfoot = listTable.querySelector('tfoot');
let wordValue = document.getElementById("w").value;
let engValue = document.getElementById("m").value;
let pronunValue = document.getElementById("p").value;
let trHTML = '<tr>' +
'<td>' + wordValue + '</td>' +
'<td>' + engValue + '</td>' +
'<td>' + pronunValue + '</td>' + '<td><button class="deletethis" type="button" title="delete this row">X</button></td>' +
'</tr>';

tfoot.closest('tfoot').insertAdjacentHTML('beforebegin', trHTML);
}
}
document.addEventListener('click', (e) => {
let thisTarget = e.target;
let thisBtn = thisTarget.closest('.deletethis');
if (thisBtn) {
e.preventDefault();
thisTarget.closest('tr').remove();
}
})
document.getElementsByClassName('.deletethismaybe').onclick = function() {
let thatTarget = e.target;
let thatBtn = thatTarget.closest('.deletethismaybe')
if (thatBtn) {
e.preventDefault();
thatTarget.closest('table').remove();
}}
</script>
</body>
</html>

这是因为您创建的事件侦听器只侦听最初已经创建的事件。当在DOM中添加新元素时,您还必须为它们添加另一个事件侦听器。

下面是一个例子:

<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul id="lists">
<li class="list-item">
<div>List #1</div>
<button class="btn-delete">Delete</button>
</li>
</ul>
<div>
<button id="btn-add">Add new item to list</button>
</div>
<script>
const listsEl = document.getElementById('lists');
// Delete button elements
let deleteBtnEls = document.querySelectorAll('.btn-delete');
const deleteBtnOnClick = (e) => {
const listItemEl = e.target.closest('.list-item');
listsEl.removeChild(listItemEl);
};
const removeEventListeners = () => {
deleteBtnEls.forEach((deleteBtnEl) => {
deleteBtnEl.removeEventListener('click', deleteBtnOnClick);
});
};
const updateEventListeners = () => {
// remove existing event listeners to prevent duplicate event listeners
removeEventListeners();
// get the updated list of delete button elements
deleteBtnEls = document.querySelectorAll('.btn-delete');
deleteBtnEls.forEach((deleteBtnEl) => {
deleteBtnEl.addEventListener('click', deleteBtnOnClick);
});
};
// Add new item button element
const addBtnEl = document.getElementById('btn-add');
addBtnEl.addEventListener('click', () => {
const newListItemEl = document.createElement('li');
newListItemEl.className = 'list-item';
newListItemEl.innerHTML = `
<div>List #${listsEl.childElementCount + 1}</div>
<button class="btn-delete">Delete</button>
`;
listsEl.appendChild(newListItemEl);
updateEventListeners();
});
// Initial call
updateEventListeners();
</script>
</body>
</html>

我认为你必须尝试理解JavaScript事件委托. 在谷歌上有很多关于这个的教程,例如1、2、3,还有更多。
如果你了解它是如何工作的,它将是很容易和非常有用的,你不需要创建或调用许多许多事件监听器。

让我们看看我的例子。

let addNewBtn = document.getElementById('add-new-btn');
addNewBtn.onclick = function() {
let newBtnHTML = '<button class="addtext" type="button">Add some text</button>';
document.getElementById('new-button-placeholder').insertAdjacentHTML('beforeend', newBtnHTML);
};

// below is how event delegation works.
// start with listen for click event on root element (`document`)
document.addEventListener('click', (e) => {
let thisTarget = e.target;
// the code above is to get `.target` property of clicked element for use later.
let thisBtn = thisTarget.closest('.addtext');
// the code above is to get closest button that has `addtext` in the class value. If this button is not exists then it will not go inside the `if` below.
if (thisBtn) {
// if this button exists.
e.preventDefault();// this is for prevent default action in case of form submit. It is no need in this example but just in case you may have to use it later.
// now add some text to `.debug` HTML element.
let someText = 'Hello world';
document.querySelector('.debug').insertAdjacentHTML('beforeend', '<p>' + someText + '</p>');
}
// if button is not exists, it will be ignore and has nothing to work here anymore.
});
.debug {
border: 2px dashed #ccc;
margin-bottom: 20px;
padding: 10px;
}
<div class="debug"></div>
<button class="addtext" type="button">Add some text</button>
<button id="add-new-btn" type="button">Add new button that will be clicked and add some text</button>
<hr>
<div id="new-button-placeholder"></div>

请阅读上面的代码注释,因为我一步一步地描述了所有内容。
当你点击添加一些文本添加新的按钮,将点击并添加一些文本按钮。新添加的按钮将以与现有按钮相同的方式工作,而无需调用或添加任何新的事件侦听器。

这就是事件委托的工作方式。


现在开始工作。

  1. 由JS动态添加的HTML不应该使用相同的id。删除按钮与id="deletethismaybe"或任何与id=".."具有相同的值,当你添加时应省略。使用class=".."代替。
  2. 尽可能在所有内容上使用描述性名称。没有deletethismaybethatBtn等,因为你将来会混淆自己。
  3. tdth只能在tr内,不能在div内。所以,<div class="boxy_gril">是无效的HTML!

document.getElementById("addtable").onclick = function() {
let puttable = document.getElementById("ntable");
let section = puttable.querySelector('section');
let tableHTML = '<br><br>' + '<table class="list">' + '<tr>' +
'<th scope="col">' + 'Word' + '</td>' +
'<th scope="col">' + 'English' + '</th>' +
'<th scope="col">' + 'Pronunciation' + '</th>' + '<th><button class="delete-table" type="button" title="delete this table">X</button></th>' +
'</tr>' +
'<tfoot><tr>' +
'<td><input type="text" class="w" required /></td>' +
'<td><input type="text" class="m" required />' +
'</td><td><input type="text" class="p" /></td>' +
'</tr>' + '<tr>' + '<td colspan="3">' + '<div class="button_boi">' + '<button type="button" class="button_boi addrow">Enter</button>' + '</div>' + '</td>' + '</tr>' + '</tfoot>' + '</table>';
section.insertAdjacentHTML('beforebegin', tableHTML);
}
// listen click event from root element (`document`).
document.addEventListener('click', (e) => {
let thisTarget = e.target;
// work with delete table button.
let deleteTableBtn = thisTarget.closest('.delete-table');
if (deleteTableBtn) {
// if delete button exists.
e.preventDefault();
thisTarget.closest('table').remove();
}
// end
// work with add row button.
let addRowBtn = thisTarget.closest('.addrow');
if (addRowBtn) {
// if add row button exists.
e.preventDefault();
// get closest table element for use later.
let thisTable = addRowBtn.closest('table');
// get input values that is under this table where add button was clicked.
let wordValue = thisTable.querySelector('.w').value;
let engValue = thisTable.querySelector('.m').value;
let pronunValue = thisTable.querySelector('.p').value;
// generate new table row (`tr`)
let trHTML = '<tr>' +
'<td>' + wordValue + '</td>' +
'<td>' + engValue + '</td>' +
'<td>' + pronunValue + '</td>' + '<td><button class="delete-row" type="button" title="delete this row">X</button></td>' +
'</tr>';
thisTable.querySelector('tfoot').insertAdjacentHTML('beforebegin', trHTML);
}
// end
// work with delete row button.
let deleteRowBtn = thisTarget.closest('.delete-row');
if (deleteRowBtn) {
// if delete row button exists.
e.preventDefault();
thisTarget.closest('tr').remove();
}
// end
})
<h1 style="font-family:verdana">Word List</h1>
<table class="list">
<tr>
<th scope="col">Word</th>
<th scope="col">English</th>
<th scope="col">Pronunciation</th>
<th scope="col"><button class="delete-table" type="button" title="delete this table">X</button></th>
</tr>
<tfoot>
<tr>
<td><input type="text" id="w" class="w" required /></td>
<td><input type="text" id="m" class="m" required /></td>
<td><input type="text" id="p" class="p" /></td>
</tr>
<tr>
<td colspan="3">
<div class="button_boi"><button type="button" class="button_boi addrow">Enter</button>
</div>
</td>
</tr>
</tfoot>
</table>
<div id="ntable" class="ntable">
<section>
</section>
</div>
<br>
<br>
<button class="button_gril" id="addtable">Add Table</button>

从上面的代码中,您将看到我只使用了一个事件侦听器,并检测它来自哪个按钮,如果按钮存在,则在if条件下使用它。

见jsfiddle

再次提示:请尝试理解事件委托正如我从一开始就描述的那样,因为我相信它会对你有用。