我创建了一个构造函数来处理自定义列表控件。我创建了一个方法,以允许用户向列表中添加元素,我需要将事件处理程序分配给列表元素(div)的单击事件。
这里是代码的简化版本。列表元素是使用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则不会发生。我做错了什么?
答案 0 :(得分:1)
您销毁以前创建的元素:
document.body.innerHTML += tmp;
如果要使用HTML标记附加,请使用insertAdjacentHMTL()
。
document.body.insertAdjacentHTML("beforeend", tmp);
现在不是经历这个破坏性的过程......
...它只是创建新内容并将其放在body
元素结束之前。
基本上,从您的编码实践中删除element.innerHTML += ...
。它从来没有必要,它效率低下,它会导致像你所描述的那样的问题。
仅供参考,.insertAdjacentHTML()
方法接收4种不同的字符串可能性作为第一个参数。每一个都指定一个相对于您调用它的元素的位置。
字符串是......
"beforebegin"
"afterbegin"
"beforeend"
"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);
};
};