Javascript: 在class里面赋值onclick
Javascript: assign onclick inside class
我创建了一个构造函数来处理自定义列表控件。我创建了一个方法来允许用户向列表中添加元素,我需要为列表元素 (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"
"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);
};
};
我创建了一个构造函数来处理自定义列表控件。我创建了一个方法来允许用户向列表中添加元素,我需要为列表元素 (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"
"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);
};
};