是否可以在不破坏后代事件监听器的情况下附加到innerHTML?

时间:2009-02-27 17:43:14

标签: javascript html javascript-events innerhtml

在以下示例代码中,我将onclick事件处理程序附加到包含文本“foo”的范围。处理程序是一个匿名函数,弹出alert()

但是,如果我分配给父节点的innerHTML,则此onclick事件处理程序将被销毁 - 单击“foo”将无法弹出警告框。

这可以修复吗?

<html>
 <head>
 <script type="text/javascript">

  function start () {
    myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    mydiv = document.getElementById("mydiv");
    mydiv.innerHTML += "bar";
  }

 </script>
 </head>

 <body onload="start()">
   <div id="mydiv" style="border: solid red 2px">
     <span id="myspan">foo</span>
   </div>
 </body>

</html>

13 个答案:

答案 0 :(得分:111)

不幸的是,即使您尝试追加,分配给innerHTML也会导致所有子元素被销毁。如果要保留子节点(及其事件处理程序),则需要使用DOM functions

function start() {
    var myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    var mydiv = document.getElementById("mydiv");
    mydiv.appendChild(document.createTextNode("bar"));
}

编辑: Bob的解决方案,来自评论。张贴你的答案,鲍勃!得到它的信任。 : - )

function start() {
    var myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    var mydiv = document.getElementById("mydiv");
    var newcontent = document.createElement('div');
    newcontent.innerHTML = "bar";

    while (newcontent.firstChild) {
        mydiv.appendChild(newcontent.firstChild);
    }
}

答案 1 :(得分:46)

使用.insertAdjacentHTML()保留事件侦听器和is supported by all major browsers。这是.innerHTML的简单单行替换。

var html_to_insert = "<p>New paragraph</p>";

// with .innerHTML, destroys event listeners
document.getElementById('mydiv').innerHTML += html_to_insert;

// with .insertAdjacentHTML, preserves event listeners
document.getElementById('mydiv').insertAdjacentHTML('beforeend', html_to_insert);

'beforeend'参数指定元素中插入HTML内容的位置。选项包括'beforebegin''afterbegin''beforeend''afterend'。他们的相应位置是:

<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->

答案 2 :(得分:4)

现在,它是2012年,jQuery已经附加并添加了完全相同的功能,在不影响当前内容的情况下添加内容。非常有用。

答案 3 :(得分:3)

作为一个轻微(但相关)的帮助,如果您使用jquery(v1.3)等javascript库来执行dom操作,则可以使用实时事件来设置处理程序,如:

 $("#myspan").live("click", function(){
  alert('hi');
});

并且它将在任何类型的jquery操作期间始终应用于该选择器。对于直播活动,请参阅:docs.jquery.com/events/live进行jquery操作,请参阅:docs.jquery.com/manipulation

答案 4 :(得分:2)

我创建了我的标记作为字符串插入,因为它比使用花哨的dom东西更少的代码和更容易阅读。

然后我把它作为一个临时元素的innerHTML,这样我就可以把那个元素的唯一的孩子带到身体上。

var html = '<div>';
html += 'Hello div!';
html += '</div>';

var tempElement = document.createElement('div');
tempElement.innerHTML = html;
document.getElementsByTagName('body')[0].appendChild(tempElement.firstChild);

答案 5 :(得分:2)

something.innerHTML + ='添加任何您想要的内容';

它为我工作。我使用此解决方案在输入文字中添加了一个按钮

答案 6 :(得分:1)

还有另一种选择:使用setAttribute而不是添加事件侦听器。像这样:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Demo innerHTML and event listeners</title>
<style>
    div {
        border: 1px solid black;
        padding: 10px;
    }
</style>
</head>
<body>
    <div>
        <span>Click here.</span>
    </div>
    <script>
        document.querySelector('span').setAttribute("onclick","alert('Hi.')");
        document.querySelector('div').innerHTML += ' Added text.';
    </script>
</body>
</html>

答案 7 :(得分:0)

丢失事件处理程序是IMO,Javascript处理DOM的方式中的错误。要避免此行为,您可以添加以下内容:

function start () {
  myspan = document.getElementById("myspan");
  myspan.onclick = function() { alert ("hi"); };

  mydiv = document.getElementById("mydiv");
  clickHandler = mydiv.onclick;  // add
  mydiv.innerHTML += "bar";
  mydiv.onclick = clickHandler;  // add
}

答案 8 :(得分:0)

你可以这样做:

var anchors = document.getElementsByTagName('a'); 
var index_a = 0;
var uls = document.getElementsByTagName('UL'); 
window.onload=function()          {alert(anchors.length);};
for(var i=0 ; i<uls.length;  i++)
{
    lis = uls[i].getElementsByTagName('LI');
    for(var j=0 ;j<lis.length;j++)
    {
        var first = lis[j].innerHTML; 
        string = "<img src=\"http://g.etfv.co/" +  anchors[index_a++] + 
            "\"  width=\"32\" 
        height=\"32\" />   " + first;
        lis[j].innerHTML = string;
    }
}

答案 9 :(得分:0)

最简单的方法是使用数组并将元素推入其中,然后将数组的后续值动态插入到数组中。 这是我的代码:

var namesArray = [];

function myclick(){
    var readhere = prompt ("Insert value");
    namesArray.push(readhere);
    document.getElementById('demo').innerHTML= namesArray;
}

答案 10 :(得分:0)

适用于具有标题和数据的任何对象数组。db.collection.aggregate({ $project: { todays_date: "$$NOW" } }) // { todays_date: ISODate("2019-07-21T09:05:46.123Z") }

https://jsfiddle.net/AmrendraKumar/9ac75Lg0/2/

jsfiddle

答案 11 :(得分:-1)

是的,如果您直接在类似onclick="sayHi()"的模板中使用参数<body onload="start()">绑定事件,则是可能的-这种方法类似于angular / vue / react / etc等框架。您也可以使用<template>来对here这样的“动态” html进行操作。它不是严格的js,但对于小型项目来说是acceptable

function start() {
  mydiv.innerHTML += "bar";
}

function sayHi() {
  alert("hi");
}
<body onload="start()">
  <div id="mydiv" style="border: solid red 2px">
    <span id="myspan" onclick="sayHi()">foo</span>
  </div>
</body>

答案 12 :(得分:-4)

我是一个懒惰的程序员。我不使用DOM,因为它似乎是额外的打字。对我来说,代码越少越好。这是我如何添加“bar”而不替换“foo”:

function start(){
var innermyspan = document.getElementById("myspan").innerHTML;
document.getElementById("myspan").innerHTML=innermyspan+"bar";
}