Pergunta

No seguinte exemplo de código, eu anexar um manipulador de eventos onclick à extensão contendo o "foo" texto. O manipulador é uma função anônima que aparece um alert().

No entanto, se eu atribuir a innerHTML do nó pai, este manipulador de eventos onclick é destruído -. Clicar em "foo" não aparecer a caixa de alerta

É este solucionáveis?

<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>
Foi útil?

Solução

Infelizmente, atribuição para innerHTML provoca a destruição de todos os elementos filhos, mesmo se você está tentando anexar. Se você quiser preservar nós filhos (e seus manipuladores de eventos), você vai precisar usar DOM funções :

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

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

Editar: solução de Bob, a partir dos comentários. Postar sua resposta, Bob! Obter crédito por isso. : -)

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

Outras dicas

Usando .insertAdjacentHTML() ouvintes conservas de eventos e é suportado por todos os principais navegadores . É uma simples substituição de uma linha para .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);

Os especifica argumento 'beforeend' onde no elemento para inserir o conteúdo HTML. As opções são 'beforebegin', 'afterbegin', 'beforeend' e 'afterend'. Suas localizações correspondentes são:

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

Agora, é de 2012, e jQuery tem acrescentar e preceder funções que fazem exatamente isso, adicionar conteúdo sem afetar o conteúdo atual. Muito útil.

Como uma pequena (mas relacionadas) asside, se você usar uma biblioteca javascript como jQuery (v1.3) para fazer a sua manipulação dom que você pode fazer uso de eventos ao vivo em que você configurar um manipulador como:

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

e será aplicada a esse seletor em todos os momentos durante qualquer tipo de manipulação jquery. Para eventos ao vivo a ver: docs.jquery.com/events/live para manipulação jquery ver: < a href = "http://docs.jquery.com/Manipulation" rel = "nofollow noreferrer"> docs.jquery.com/manipulation

Eu criei minha marcação para inserir como uma string já que é menos código e mais fácil de ler do que trabalhar com o material extravagante dom.

Então eu fiz isso innerHTML de um elemento temporário apenas para que eu pudesse tomar o primeiro e único filho desse elemento e anexar ao corpo.

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

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

something.innerHTML + = 'add o que quiser';

ele trabalhou para mim. Eu adicionei um botão para um texto de entrada usando esta solução

Há uma outra alternativa: usar setAttribute em vez de adicionar um ouvinte de evento. Como esta:

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

Perder manipuladores de eventos é, IMO, um erro na forma como lida com o Javascript DOM. Para evitar esse comportamento, você pode adicionar o seguinte:

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
}

Você poderia fazê-lo como este:

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

A maneira mais fácil é a utilização de uma matriz e empurram os elementos para ele e, em seguida, inserir os valores subsequentes da matriz para a matriz de forma dinâmica. Aqui está o meu código:

var namesArray = [];

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

Sim, é possível se você vincular eventos usando argumento onclick="sayHi()" diretamente no modelo semelhante como o seu <body onload="start()"> - esta abordagem similar às estruturas angular / vue / reagir / etc. Você também pode usar <template> para operar em 'dinâmico 'html como aqui . Não são rigorosos js discretos no entanto, é aceitável para pequenos projetos

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>

Para qualquer matriz objeto com cabeçalho e 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>

Eu sou um programador preguiçoso. Não uso DOM, porque parece que digitação extra. Para mim, o código menos, melhor. Aqui está como eu gostaria de acrescentar "bar" sem substituir "foo":

function start(){
var innermyspan = document.getElementById("myspan").innerHTML;
document.getElementById("myspan").innerHTML=innermyspan+"bar";
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top