Javascript:在类内分配onclick

标签 javascript html class onclick

我创建了一个构造函数来处理自定义列表控件。我创建了一个方法以允许用户将元素添加到列表中,我需要将事件处理程序分配给列表元素 (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);

现在不要经历这个破坏性的过程......

  1. 将现有的 DOM 节点序列化为 HTML
  2. 将新的 HTML 片段连接到序列化节点
  3. 销毁旧节点
  4. 用新节点重新创建节点

...它只是创建新内容并将其放置在 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/

相关文章:

html - 一个 block 应该重叠两个相邻的 CSS

全局对象中定义的类中的 Javascript 静态方法

php - 一个类的实例可以更改另一个类的实例中的变量吗?

javascript - 在 D3 中对齐轴

javascript - Dojo 工具包关闭外部对话框

javascript - 在 jQuery 中获取下拉更改值的事件

java - 防止针对jsp页面中的跨站点脚本进行XSS攻击

javascript - 来自 .text() 的 JQuery 添加

c# - 如何替换 HTML 内容?

c++ - KeyBoardEvents C++ 的数据结构