Javascript:在类内分配onclick

Javascript:在类内分配onclick,javascript,html,class,onclick,Javascript,Html,Class,Onclick,我创建了一个将处理自定义列表控件的构造函数。我创建了一个方法以允许用户向列表中添加元素,并且我需要为列表元素(div)的click事件分配事件处理程序 这里是代码的简化版本。列表元素是使用innerHTML属性和字符串模板创建的,我在该模板上替换特定部分。之后,我根据元素的id获取元素,并在闭包中为其分配一个函数: function prueba(){ var plantilla = '<div id="«id»">«texto»</div>'; var

我创建了一个将处理自定义列表控件的构造函数。我创建了一个方法以允许用户向列表中添加元素,并且我需要为列表元素(div)的click事件分配事件处理程序

这里是代码的简化版本。列表元素是使用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);
    };
};

这发生在冰鼬和铬中。当我在模板中添加“onclick=f(«id»)”时不会发生这种情况(由于分配的函数作用域,我在这里不能这样做),如果我使用document.createElement,也不会发生这种情况。我做错了什么?

执行此操作时,您会销毁以前创建的元素:

document.body.innerHTML += tmp;
如果要使用HTML标记进行追加,请使用
insertAdjacentHMTL()

document.body.insertAdjacentHTML("beforeend", tmp);
现在,与其经历这个破坏性的过程

  • 将现有DOM节点序列化为HTML
  • 将新的HTML片段连接到序列化节点
  • 销毁旧节点
  • 使用新节点重新创建节点
  • …它只是创建新内容并将其放置在
    正文
    元素结束之前

    基本上,从您的编码实践中删除
    element.innerHTML+=…
    。它从来都不是必需的,它效率低下,并且会导致像您所描述的那样的问题


    仅供参考,
    .insertAdjacentHTML()
    方法接收4种不同的字符串可能性作为第一个参数。每个元素都指定一个相对于要调用它的元素的位置

    字符串是

    • “开始之前”
    • “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);
        };
    };
    
    函数prueba(){
    var plantilla=«文本»;
    var f=函数(nombre){
    返回函数(){console.log('mi nombre es'+nombre)};
    };
    this.agregar=函数(id,texto){
    document.body.insertAdjacentHTML(“beforeend”,
    plantilla.replace(“«id»”,id)
    .替换(“«texto»”,texto));
    document.getElementById(id).onclick=f(id);
    };
    };
    
    insertAdjacentHTML确实解决了这个问题,谢谢!。我还有一个疑问:你说这会破坏先前创建的元素,但唯一被破坏的是分配给它们的函数(我实际上看到了新的div及其相应的文本)该函数是否被视为新元素?@carlospieto:它会破坏元素以及与之相关的任何东西,类似于事件处理函数。然后它重新创建它们。这是非常低效的。假设在
    主体中总共有100个DOM节点。JS引擎需要遍历每个节点,将它们转换为HTML字符串,将新HTML添加到该字符串的末尾,销毁旧节点,解析刚刚创建的HTML,创建新节点并将它们放入
    正文中。所以,是的,它基本上会破坏它们,然后再重新创建它们,这是浪费的……可能会有一些优化,使其比这稍微更有效率,但谁知道呢。这个原则是破坏性的,并且肯定会清除事件处理程序和其他东西,因此
    .insertAdjacentHTML
    非常有帮助。
    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);
        };
    };