javascript - 如果使用javascript动态添加按钮,如何知道单击了哪个按钮?
问题描述
我不知道如何解决这个问题,如果有人知道如何解决,请告诉我。如果需要,我会亲自发送代码以找出错误。
有两个容器:左和右。在左侧,我从文本框和单选按钮(活动/非活动)中获取标题、描述和状态(活动/非活动)的值。然后在按下提交按钮后,所有值都填充到右侧容器表中,每次单击提交按钮后附加编辑和删除按钮。我想删除单击删除按钮的特定行。但是我不知道如何访问该按钮,而 onclick 功能(doDelete())在所有按钮中都是相同的。
function fillData() {
var table = document.getElementById("myTable");
var counter = table.querySelectorAll('tr').length;
var key = counter;
var row = table.insertRow(counter);
row.id = "row-" + key;
var titleCell = row.insertCell(0);
var descCell = row.insertCell(1);
var statusCell = row.insertCell(2);
var actionCell = row.insertCell(3);
var editButton = document.createElement("button");
editButton.innerText = "Edit";
editButton.id = "edit-" + key;
editButton.setAttribute("onclick", "doEdit()");
var delButton = document.createElement("button");
delButton.innerText = "Delete";
delButton.id = "delete-" + key;
delButton.setAttribute("onclick", "doDelete()");
titleCell.innerHTML = document.getElementById("panel-title").value;
descCell.innerHTML = document.getElementById("panel-description").value;
statusCell.innerHTML = (function () {
var radios = document.getElementsByName("status");
for (i = 0, len = radios.length; i < len; i++) {
if (radios[i].checked) {
return radios[i].value;
}
}
}());
actionCell.appendChild(editButton);
actionCell.appendChild(delButton);
var delBtnArr = document.querySelectorAll('input[type="button"]');
console.log(delBtnArr);
}
实际结果:按下删除按钮后,整行都被删除。预期结果:按下删除按钮后,单击按钮的特定行将被删除。
解决方案
事件委托
将祖先绑定/注册到事件
动态添加的标签不能绑定到事件处理程序/侦听器,只有自页面加载以来已经存在的标签可以。因此,对于多个动态添加的标签(例如按钮),您必须找到它们都共享不常见的祖先标签并将其绑定到您需要侦听的任何事件。对于您的按钮,它可以是最接近的祖先table
*(推荐)最远window
:
// On-event property. ALWAYS PASS THE EVENT OBJECT table.onclick = function(event) {...
或者
// Event Listener. Abbreviating the [Event Object][2] is OK, but you must be consistent. table.addEventListener('click', function(e) {...
不要使用事件属性 <button onclick="func()"...
<button onclick="func()"...
✱从技术上讲,最接近的祖先是tbody
即使您没有将其添加到表中,浏览器也会默认添加它。
用途Event.target
和Event.currentTarget
特性
请记住传递事件对象,因为您需要它来...
...找出您实际使用
event.target
属性单击的按钮。...获取对具有
event.currentTarget
属性的表的引用。...可能会阻止默认行为,例如使用
event.preventDefault()
方法阻止表单提交到服务器。
查看演示,它将包含有关事件处理程序的特定详细信息。
演示
演示中评论的详细信息
var table = document.querySelector("table");
document.forms[0].onsubmit = fillData;
/*
This onevent property handler has two functions note it is bound
to the table NOT the buttons.
There's two conditionals and they only focus on classNames of
either .del or .edit. Once it's determined if the clicked tag has
one of these classes then the appropriate function is called.
If neither class was clicked there's no opportunity for anything
else to act on the click because both conditionals end with
return false thereby terminating the event handler.
*/
table.onclick = function(e) {
if (e.target.className === 'del') {
delRow(e);
return false;
}
if (e.target.className === 'edit') {
editRow(e);
return false;
}
};
function fillData(e) {
var ui = e.target.elements;
e.preventDefault();
var idx = table.rows.length;
var row = table.insertRow();
row.id = 'r-' + idx;
var cell1 = row.insertCell(0);
var data1 = ui.title.value;
cell1.textContent = data1;
var cell2 = row.insertCell(1);
var data2 = ui.desc.value;
cell2.textContent = data2;
var cell3 = row.insertCell(2);
var data3 = ui.chk.checked ? 'Active' : 'Inactive';
cell3.textContent = data3;
var cell4 = row.insertCell(3);
var btns = `
<button class='edit'>📝</button>
<button class='del'>❌</button>`;
cell4.innerHTML = btns;
}
/*
Reference the .closest() row from clicked button
Get that row's id and split() it at the dash and pop() the number.
Then get a reference to the bound ancestor (table) and deleteRow() with the new number you just got.
*/
function delRow(e) {
var row = e.target.closest('tr');
var idx = row.id.split('-').pop();
e.currentTarget.deleteRow(idx);
}
/*
Same as before get the index number from the closest row's id.
Reference the table and use the .rows property and number.
This reference will now allow you to use the .cells property.
Use the .cells property to toggle the contenteditable attribute
on the first three cells.
*/
function editRow(e) {
var row = e.target.closest('tr');
var idx = row.id.split('-').pop();
var R = e.currentTarget.rows[idx];
for (let c = 0; c < 3; c++) {
var cell = R.cells[c];
if (cell.hasAttribute('contenteditable')) {
cell.removeAttribute('contenteditable');
} else {
cell.setAttribute('contenteditable', true);
}
}
}
body {
font: 400 16px/25px Consolas;
display: flex;
justify-content: space-between;
}
fieldset {
width: fit-content
}
input,
label,
textarea {
font: inherit
}
input,
label,
button {
display: inline-block;
height: 25px;
}
#title {
width: 27.5ch;
}
#chk {
display: none;
}
#chk+label::after {
content: '\2610';
font-size: 20px;
vertical-align: middle;
}
#chk:checked+label::after {
content: '\2611';
}
[type='reset'] {
margin-left: 5%
}
td {
min-width: 60px;
border-bottom: 1px solid #000;
height: 25px;
}
tr td:last-child {
border-bottom-color: transparent;
}
button {
width: 35px;
text-align: center;
}
<form id='data'>
<fieldset>
<legend>Enter Data</legend>
<input id='title' type='text' placeholder='Title'><br>
<textarea id='desc' rows='3' cols='25' placeholder='Description'></textarea><br>
<input id='chk' type='checkbox'>
<label for='chk'>Active </label>
<input type='reset'>
<input type='submit'>
</fieldset>
</form>
<hr>
<table></table>
推荐阅读
- sql - 如果查询结果在 BigQuery 中没有记录,则显示默认值
- templates - Helm 图表嵌套循环
- javascript - Rails 5 / JavaScript:仅动态更新页面上已更新的记录属性
- postgresql - 使用第一次插入的结果将记录插入多个表
- c++ - 在 Win32 Api 中使用多线程
- java - 在 JavaFX 中使用 CheckBox 过滤 ObservableList
- json - Laravel API 返回图片链接
- linux - 用于迭代目录并创建 tar 文件的 bash 脚本
- hapi-fhir - 如何访问患者 ID?
- scikit-learn - Joblib 在 Jupyter 实验室中不起作用