Javascript 是否可以在不破坏子体的情况下附加到innerHTML';事件侦听器?

Javascript 是否可以在不破坏子体的情况下附加到innerHTML';事件侦听器?,javascript,html,innerhtml,dom-events,Javascript,Html,Innerhtml,Dom Events,在下面的示例代码中,我将onclick事件处理程序附加到包含文本“foo”的范围。处理程序是一个匿名函数,它会弹出一个警报() 但是,如果我分配给父节点的innerHTML,此onclick事件处理程序将被销毁-单击“foo”无法弹出警报框 这能修好吗 <html> <head> <script type="text/javascript"> function start () { myspan = document.getElementBy

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

但是,如果我分配给父节点的
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>

函数启动(){
myspan=document.getElementById(“myspan”);
myspan.onclick=function(){alert(“hi”);};
mydiv=document.getElementById(“mydiv”);
mydiv.innerHTML+=“bar”;
}
福

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

编辑:来自评论的Bob的解决方案。把你的答案贴出来,鲍勃!获得学分。:-)


在我看来,丢失事件处理程序是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
}
作为一个轻微的(但相关的)帮助,如果您使用诸如jquery(v1.3)之类的javascript库来进行dom操作,那么您可以利用实时事件来设置如下处理程序:

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

在任何类型的jquery操作过程中,它都将始终应用于该选择器。有关实时事件,请参见:关于jquery操作,请参见:

我是一个懒惰的程序员。我不使用DOM,因为它看起来像是额外的键入。对我来说,代码越少越好。下面是我如何添加“bar”而不替换“foo”:


现在是2012年,jQuery有append和prepend函数,它们可以精确地执行此操作,添加内容而不影响当前内容。非常有用。

我创建了作为字符串插入的标记,因为它的代码更少,阅读起来也更容易

然后我将它作为一个临时元素的innerHTML,这样我就可以获取该元素的唯一子元素并附加到主体

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

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

您可以这样做:

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;
    }
}
var-anchors=document.getElementsByTagName('a');
var指数_a=0;
var uls=document.getElementsByTagName('UL');
window.onload=function(){alert(anchors.length);};

对于(var i=0;i使用
.insertAdjacentHTML()
保留事件侦听器,并且。它是
.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);

还有另一种选择:使用
setAttribute
而不是添加事件侦听器。如下所示:


演示innerHTML和事件侦听器
div{
边框:1px纯黑;
填充:10px;
}
点击这里。
document.querySelector('span').setAttribute(“onclick”,“alert('Hi')”);
document.querySelector('div').innerHTML+='Added text';

something.innerHTML+=“添加您想要的任何内容”


我使用这个解决方案在输入文本中添加了一个按钮。最简单的方法是使用数组并将元素推入其中,然后将数组的后续值动态插入数组。 这是我的密码:

var namesArray = [];

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

是的,如果您在类似于您的
的模板中直接使用标记属性
onclick=“sayHi()”
绑定事件,这是可能的-这种方法类似于/vue/react/等。您也可以使用类似于“动态”html的操作。它不是严格的、不引人注目的js,但适用于小型项目

函数开始(){
mydiv.innerHTML+=“bar”;
}
函数sayHi(){
警报(“hi”);
}

用于任何带有标头和数据的对象数组。
jsfiddle


常量userObjectArray=[{
姓名:“Ajay”,
年龄:27岁,
身高:5.10,
地址:“班加罗尔”
}, {
姓名:“维杰”,
年龄:24岁,
身高:5.10,
地址:“班加罗尔”
}, {
名称:“迪内什”,
年龄:27岁,
身高:5.10,
地址:“班加罗尔”
}];
const headers=Object.keys(userObjectArray[0]);
var tr1=document.createElement('tr');
var htmlHeaderStr='';
for(设i=0;i< /代码>我不认为这是一个bug。替换一个元素意味着你完全取代它。它不应该继承以前存在的东西。但是我不想替换一个元素;我只想把新的元素追加到父元素上。如果你正在替换这个元素,我会同意的,“Diodeus。不是事件处理程序,而是内层HTML。的父项。innerHTML的所有者在更改其innerHTML时不会丢失处理程序,只会丢失其内容中的任何内容。而且JavaScript不知道您只添加了新的子项,因为“x.innerHTML+=y”是字符串操作“x.innerHTML=x.innerHTML+y”的唯一语法。您不需要重新附加
mydiv.onclick
。只有内部span的onclick被
innerHTML+=
覆盖。是否有替代项可以附加HTML的任意blob?newcontent=document.createElement('div');newcontent.innerHTML=任意\u blob;而(newcontent.firstChild)mydiv.appendChild(newcontent.firstChild);很好,鲍勃!如果你把它作为一个格式良好的答案发布,我会选择它。@bobince-我已经更新了
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;
    }
}
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);
<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->
var namesArray = [];

function myclick(){
    var readhere = prompt ("Insert value");
    namesArray.push(readhere);
    document.getElementById('demo').innerHTML= namesArray;
}
<table id="myTable" border='1|1'></table>

<script>
  const userObjectArray = [{
    name: "Ajay",
    age: 27,
    height: 5.10,
    address: "Bangalore"
  }, {
    name: "Vijay",
    age: 24,
    height: 5.10,
    address: "Bangalore"
  }, {
    name: "Dinesh",
    age: 27,
    height: 5.10,
    address: "Bangalore"
  }];
  const headers = Object.keys(userObjectArray[0]);
  var tr1 = document.createElement('tr');
  var htmlHeaderStr = '';
  for (let i = 0; i < headers.length; i++) {
    htmlHeaderStr += "<th>" + headers[i] + "</th>"
  }
  tr1.innerHTML = htmlHeaderStr;
  document.getElementById('myTable').appendChild(tr1);

  for (var j = 0; j < userObjectArray.length; j++) {
    var tr = document.createElement('tr');
    var htmlDataString = '';
    for (var k = 0; k < headers.length; k++) {
      htmlDataString += "<td>" + userObjectArray[j][headers[k]] + "</td>"
    }
    tr.innerHTML = htmlDataString;
    document.getElementById('myTable').appendChild(tr);
  }

</script>