webentwicklung-frage-antwort-db.com.de

Ist es möglich, an innerHTML anzuhängen, ohne die Ereignis-Listener der Nachkommen zu zerstören?

Im folgenden Beispielcode füge ich einen onclick-Ereignishandler an den Bereich an, der den Text "foo" enthält. Der Handler ist eine anonyme Funktion, die eine Warnung () anzeigt.

Wenn ich jedoch der innerHTML des übergeordneten Knotens zuweise, wird diese onclick-Ereignisprozedur zerstört. Wenn Sie auf "foo" klicken, wird das Benachrichtigungsfeld nicht angezeigt.

Ist das fixierbar?

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

Leider führt die Zuweisung zu innerHTML zur Zerstörung aller untergeordneten Elemente, selbst wenn Sie versuchen, anzufügen. Wenn Sie untergeordnete Knoten (und ihre Ereignishandler) beibehalten möchten, müssen Sie die DOM-Funktionen verwenden:

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

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

Edit: Bobs Lösung aus den Kommentaren. Poste deine Antwort, Bob! Holen Sie sich Kredit dafür. :-)

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);
    }
}
104
Ben Blank

Durch die Verwendung von .insertAdjacentHTML() bleiben Ereignis-Listener erhalten und wird von allen gängigen Browsern unterstützt . Es ist ein einfacher einzeiliger Ersatz für .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);

Das Argument 'beforeend' gibt an, wo im Element der HTML-Inhalt eingefügt werden soll. Optionen sind 'beforebegin', 'afterbegin', 'beforeend' und 'afterend'. Ihre entsprechenden Standorte sind:

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

Nun ist es 2012, und jQuery verfügt über Funktionen zum Anhängen und Voranstellen, die genau dies tun und Inhalte hinzufügen, ohne den aktuellen Inhalt zu beeinträchtigen. Sehr hilfreich.

4
rocketsarefast

Als leichte (aber verwandte) Angelegenheit: Wenn Sie eine Javascript-Bibliothek wie jquery (v1.3) verwenden, um Ihre Dom-Manipulation durchzuführen, können Sie Live-Events verwenden, wobei Sie einen Handler wie folgt einrichten: 

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

und es wird zu jeder Zeit während dieser Art von Jquery-Manipulation auf diesen Selektor angewendet. Für Live-Events siehe: docs.jquery.com/events/live für die Bearbeitung von Jquery siehe: docs.jquery.com/manipulation

3
Cargowire

something.innerHTML + = 'alles hinzufügen, was Sie möchten';

es hat für mich funktioniert. Ich habe mit dieser Lösung eine Schaltfläche zu einem Eingabetext hinzugefügt

2
KawaiKx

Ich habe mein Markup erstellt, um es als Zeichenfolge einzufügen, da es weniger Code enthält und einfacher zu lesen ist, als mit dem ausgefallenen Dom-Material zu arbeiten.

Dann machte ich es innerHTML aus einem temporären Element, nur damit ich das einzige Kind dieses Elements nehmen und am Körper befestigen konnte.

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

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

Eventhandler zu verlieren ist, IMO, ein Fehler in der Art und Weise, wie Javascript das DOM behandelt. Um dieses Verhalten zu vermeiden, können Sie Folgendes hinzufügen:

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

Es gibt eine andere Alternative: Verwenden Sie setAttribute, anstatt einen Ereignis-Listener hinzuzufügen. So was: 

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

1
Frank Conijn

Für jedes Objektarray mit Header und Daten .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>
0
AKS

Am einfachsten ist es, ein Array und Push-Elemente darin zu verwenden und die nachfolgenden Werte des Arrays dynamisch in das Array einzufügen ..__ Hier ist mein Code:

var namesArray = [];

function myclick(){
    var readhere = Prompt ("Insert value");
    namesArray.Push(readhere);
    document.getElementById('demo').innerHTML= namesArray;
}
0
Anoop Anson

Du könntest es so machen:

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;
    }
}
0
Rishabh gupta

Ja, es ist möglich, dass Sie Ereignisse mit dem Argument onclick="sayHi()" direkt in eine Vorlage binden, ähnlich wie mit Ihrem <body onload="start()"> - dieser Ansatz ähnelt Frameworks angle/vue/react/etc. Sie können auch <template> verwenden, um 'dynamische' HTML-Dateien wie hier zu bearbeiten. Es ist nicht streng unauffällig, aber es ist akzeptabel für kleine Projekte

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