gpt4 book ai didi

动态创建元素时 Javascript 事件处理程序消失

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:52:44 26 4
gpt4 key购买 nike

鉴于下面的最小代码示例,我希望每个表行中的每个动态创建的按钮都会根据关联的 onclick 事件处理程序生成警报。

class A {
constructor() {
var root = document.getElementById('root');
root.innerHTML =
`
<button id="btn-add">+</button>
<table id="tbl"></table>
`
document.getElementById('btn-add').onclick = () => {
this.add()
}
this.counter = 0
}
add() {
var tbl = document.getElementById('tbl').innerHTML +=
`
<li>
<button id="${this.counter}-btn-rmv">-</button>
</li>

`
document.getElementById(this.counter + '-btn-rmv').onclick = () => {
alert('Click event!')
} //<-- each should have an event handler!
this.counter++
}
}
new A()
<div id="root" />

然而,只有最后一行中的最后一个按钮具有功能性事件处理程序并产生警报。由于某种原因,先前创建的按钮上的事件处理程序已被删除。我对 javascript 不够熟悉,无法理解这里出了什么问题,请告诉我。

最佳答案

问题是

var tbl = document.getElementById('tbl').innerHTML +=
`
<li>
<button id="${this.counter}-btn-rmv">-</button>
</li>
`

这在功能上等同于

const existingHTML = document.getElementById('tbl').innerHTML;
document.getElementById('tbl').innerHTML = '';
document.getElementById('tbl').innerHTML = existingHTML + ...

容器元素基本上被清除,然后浏览器根据新的+= 连接字符串重新解析其内容。文档中不再存在旧元素,因此无法触发附加到旧元素的监听器(并且单击除最后一个按钮之外的任何 - 按钮都不会执行任何操作)。

改用 insertAdjacentHTML,它不会破坏现有元素:

class A {
constructor() {
var root = document.getElementById('root');
root.innerHTML =
`
<button id="btn-add">+</button>
<table id="tbl"></table>
`
document.getElementById('btn-add').onclick = () => {
this.add()
}
this.counter = 0
}
add() {
document.getElementById('tbl').insertAdjacentHTML('beforeend', `
<li>
<button id="${this.counter}-btn-rmv">-</button>
</li>

`);
document.getElementById(this.counter + '-btn-rmv').onclick = () => {
alert('Click event!')
} //<-- each should have an event handler!
this.counter++
}
}
new A()
<div id="root" />

也就是说,动态创建的 ID 有点代码味道 - 考虑改用事件委托(delegate):

class A {
constructor() {
var root = document.getElementById('root');
root.innerHTML =
`
<button id="btn-add">+</button>
<table id="tbl"></table>
`
root.addEventListener('click', ({
target
}) => {
if (target.matches('[data-btn-rmv]')) {
console.log('Clicked on', target.dataset.btnRmv);
}
});

document.getElementById('btn-add').onclick = () => {
this.add()
}
this.counter = 0
}
add() {
document.getElementById('tbl').insertAdjacentHTML('beforeend', `
<li>
<button data-btn-rmv=${this.counter}>-</button>
</li>

`)
this.counter++
}
}
new A()
<div id="root" />

关于动态创建元素时 Javascript 事件处理程序消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58441320/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com