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

发布于 2024-07-13 21:47:58 字数 735 浏览 5 评论 0原文

在以下示例代码中,我将一个 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>

In the following example code, I attach an onclick event handler to the span containing the text "foo". The handler is an anonymous function that pops up an alert().

However, if I assign to the parent node's innerHTML, this onclick event handler gets destroyed - clicking "foo" fails to pop up the alert box.

Is this fixable?

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

瀟灑尐姊 2024-07-20 21:47:58

使用 .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);

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

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

Using .insertAdjacentHTML() preserves event listeners, and is supported by all major browsers. It's a simple one-line replacement for .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);

The 'beforeend' argument specifies where in the element to insert the HTML content. Options are 'beforebegin', 'afterbegin', 'beforeend', and 'afterend'. Their corresponding locations are:

<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->
悲喜皆因你 2024-07-20 21:47:58

不幸的是,即使您尝试追加,对 innerHTML 的赋值也会导致所有子元素被破坏。 如果您想保留子节点(及其事件处理程序),则需要使用 DOM 函数

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

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

编辑:鲍勃的解决方案,来自评论。 发表你的答案,鲍勃! 获得荣誉。 :-)

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);
    }
}

Unfortunately, assignment to innerHTML causes the destruction of all child elements, even if you're trying to append. If you want to preserve child nodes (and their event handlers), you'll need to use DOM functions:

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

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

Edit: Bob's solution, from the comments. Post your answer, Bob! Get credit for it. :-)

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);
    }
}
蓬勃野心 2024-07-20 21:47:58

现在是 2012 年,jQuery 具有附加和前置函数来完成此操作,添加内容而不影响当前内容。 很有用。

Now, it is 2012, and jQuery has append and prepend functions that do exactly this, add content without effecting current content. Very useful.

混吃等死 2024-07-20 21:47:58

我创建了我的标记作为字符串插入,因为它比使用花哨的 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);

I created my markup to insert as a string since it's less code and easier to read than working with the fancy dom stuff.

Then I made it innerHTML of a temporary element just so I could take the one and only child of that element and attach to the body.

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

var tempElement = document.createElement('div');
tempElement.innerHTML = html;
document.getElementsByTagName('body')[0].appendChild(tempElement.firstChild);
白况 2024-07-20 21:47:58

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

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

它将应用于该处理 程序在任何类型的 jquery 操作期间始终使用选择器。 对于实时事件,请参阅:docs.jquery.com/events/live 对于 jquery 操作,请参阅:< a href="http://docs.jquery.com/Manipulation" rel="nofollow noreferrer">docs.jquery.com/manipulation

As a slight (but related) asside, if you use a javascript library such as jquery (v1.3) to do your dom manipulation you can make use of live events whereby you set up a handler like:

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

and it will be applied to that selector at all times during any kind of jquery manipulation. For live events see: docs.jquery.com/events/live for jquery manipulation see: docs.jquery.com/manipulation

可是我不能没有你 2024-07-20 21:47:58

还有另一种选择:使用 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>

There is another alternative: using setAttribute rather than adding an event listener. Like this:

<!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>

黑凤梨 2024-07-20 21:47:58

是的,如果您直接在模板中使用标签属性 onclick="sayHi()" 绑定事件,就像您的 一样,这是可能的- 这种方法类似于 Angular/Vue/React/等框架。 您还可以使用

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>

Yes it is possible if you bind events using tag attribute onclick="sayHi()" directly in template similar like your <body onload="start()"> - this approach similar to frameworks angular/vue/react/etc. You can also use <template> to operate on 'dynamic' html like here. It is not strict unobtrusive js however it is acceptable for small projects

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>

通知家属抬走 2024-07-20 21:47:58

在我看来,丢失事件处理程序是 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
}

Losing event handlers is, IMO, a bug in the way Javascript handles the DOM. To avoid this behavior, you can add the following:

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
}
另类 2024-07-20 21:47:58

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

var namesArray = [];

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

The easiest way is to use an array and push elements into it and then insert the array subsequent values into the array dynamically.
Here is my code:

var namesArray = [];

function myclick(){
    var readhere = prompt ("Insert value");
    namesArray.push(readhere);
    document.getElementById('demo').innerHTML= namesArray;
}
山人契 2024-07-20 21:47:58

Element#append可用于在另一个元素的末尾插入元素。 要从字符串插入 HTML,Range#createContextualFragment<可以使用/code>

const mydiv = document.getElementById("mydiv");
mydiv.append(document.createRange().createContextualFragment(`
    <div>Some HTML here</div>
`));

或者只是附加文本:

mydiv.append("some text"); // no need for document.createTextNode

如果您不需要直接插入 HTML,请考虑使用 DOM 方法来创建结构:

mydiv.append(
    Object.assign(document.createElement('div'), 
              { textContent: 'some text', className: 'my-class' }),
    document.createElement('hr'),
    "some more text"
); 
// can append multiple elements (mixed with strings which are converted to text nodes)

在相关说明中,相应的 Element#prepend 方法可用于在开头插入元素(第一个子元素之前)一个元素的。

Element#append can be used to insert elements at the end of another element. To insert HTML from a string, Range#createContextualFragment can be used.

const mydiv = document.getElementById("mydiv");
mydiv.append(document.createRange().createContextualFragment(`
    <div>Some HTML here</div>
`));

Or to just append text:

mydiv.append("some text"); // no need for document.createTextNode

If you don't need to insert HTML directly, consider using DOM methods to create the structure instead:

mydiv.append(
    Object.assign(document.createElement('div'), 
              { textContent: 'some text', className: 'my-class' }),
    document.createElement('hr'),
    "some more text"
); 
// can append multiple elements (mixed with strings which are converted to text nodes)

On a related note, the corresponding Element#prepend method can be used to insert elements at the start (before the first child) of an element.

清晨说晚安 2024-07-20 21:47:58

你可以这样做:

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;
    }
}

You could do it like this:

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;
    }
}
静水深流 2024-07-20 21:47:58

some.innerHTML += '添加你想要的任何内容';

它对我有用。 我使用此解决方案向输入文本添加了一个按钮

something.innerHTML += 'add whatever you want';

it worked for me. I added a button to an input text using this solution

姜生凉生 2024-07-20 21:47:58

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

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

<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>

For any object array with header and data.jsfiddle

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

<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>
冷了相思 2024-07-20 21:47:58

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

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

I'm a lazy programmer. I don't use DOM because it seems like extra typing. To me, the less code the better. Here's how I would add "bar" without replacing "foo":

function start(){
var innermyspan = document.getElementById("myspan").innerHTML;
document.getElementById("myspan").innerHTML=innermyspan+"bar";
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文