我创建了一个构造函数来处理自定义列表控件。我创建了一个方法以允许用户将元素添加到列表中,我需要将事件处理程序分配给列表元素 (divs) 的点击事件。
代码的简化版本在这里。列表元素是使用 innerHTML 属性和我在其上替换特定部分的字符串模板创建的。后来我通过它的 id 获取元素并在闭包中为它分配一个函数:
function prueba(){
var plantilla = '<div id="«id»">«texto»</div>';
var f = function(nombre){
return function(){console.log('mi nombre es ' + nombre)};
};
this.agregar = function(id, texto){
var tmp = plantilla.replace('«id»', id);
tmp = tmp.replace('«texto»', texto);
document.body.innerHTML += tmp;
document.getElementById(id).onclick = f(id);
};
};
问题是,显然,事件处理程序未分配给先前创建的 div,因此仅由最后一个保留,因为可以使用以下代码对其进行测试:
var p = new prueba;
p.agregar('i1', 'texto1');
console.log(document.getElementById('i1').onclick.toString());//shows the function code
p.agregar('i2', 'texto2');
console.log(document.getElementById('i2').onclick.toString());//shows the function code
console.log(document.getElementById('i1').onclick.toString());//returns 'null' error
p.agregar('i3', 'texto3');
console.log(document.getElementById('i3').onclick.toString());//shows the function code
console.log(document.getElementById('i2').onclick.toString());//returns 'null' error
这发生在 Iceweasel 和 Chromium 中。当我在模板中添加“onclick = f(«id»)”时不会发生这种情况(由于分配的函数范围我不能在这里这样做),如果我使用 document.createElement 也不会发生这种情况。我做错了什么?
最佳答案
这样做会破坏之前创建的元素:
document.body.innerHTML += tmp;
如果您想使用 HTML 标记附加,请改用 insertAdjacentHMTL()
。
document.body.insertAdjacentHTML("beforeend", tmp);
现在不要经历这个破坏性的过程......
- 将现有的 DOM 节点序列化为 HTML
- 将新的 HTML 片段连接到序列化节点
- 销毁旧节点
- 用新节点重新创建节点
...它只是创建新内容并将其放置在 body
元素结束之前。
基本上,从您的编码实践中删除 element.innerHTML += ...
。从来没有必要,它效率低下,并且会导致您所描述的问题。
仅供引用,.insertAdjacentHTML()
方法接收 4 种不同的字符串可能性作为第一个参数。每一个都指定一个相对于您调用它的元素的位置。
字符串是...
“beforebegin”
“afterbegin”
“之前”
“afterend”
标签是不言自明的。它们分别将新内容定位在当前元素之前、当前元素内的开头、当前元素内的末尾或当前元素之后。
您的完整代码如下所示,我也将其缩短了一点,因为此处确实不需要 tmp
:
function prueba(){
var plantilla = '<div id="«id»">«texto»</div>';
var f = function(nombre){
return function(){console.log('mi nombre es ' + nombre)};
};
this.agregar = function(id, texto){
document.body.insertAdjacentHTML("beforeend",
plantilla.replace('«id»', id)
.replace('«texto»', texto));
document.getElementById(id).onclick = f(id);
};
};
关于Javascript:在类内分配onclick,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31147106/