Alternativa para innerHTML?


Me pregunto si hay una manera de cambiar el texto de cualquier cosa en HTML sin usar innerHTML.

La razón por la que estoy preguntando es porque es un poco mal visto por el W3C. Sé que es quisquilloso, pero sólo quiero saber, ¿hay alguna manera?

EDITAR: la gente parece malinterpretar lo que estoy pidiendo aquí: Quiero encontrar una manera de cambiar efectivamente el texto que se muestra.

Si tengo:

<div id="one">One</a>

InnerHTML me permite hacer esto:

var text = document.getElementsById("one");
text.innerHTML = "Two";

Y el texto en mi pantalla habrá cambiado.
No quiero añadir más texto, quiero cambiar el texto ya existente.

Author: KdgDev, 2009-04-05

11 answers

La forma recomendada es a través de la manipulación del DOM, pero puede ser bastante detallada. Por ejemplo:

// <p>Hello, <b>World</b>!</p>
var para = document.createElement('p');
para.appendChild(document.createTextNode('Hello, '));

// <b>
var b = document.createElement('b');
b.appendChild(document.createTextNode('World');
para.appendChild(b);

para.appendChild(document.createTextNode('!'));

// Do something with the para element, add it to the document, etc.

EDITAR

En respuesta a su edición, para reemplazar el contenido actual, simplemente elimine el contenido existente, luego use el código anterior para completar el nuevo contenido. Por ejemplo:

var someDiv = document.getElementById('someID');
var children = someDiv.childNodes;
for(var i = 0; i < children.length; i++)
    someDiv.removeChild(children[i]);

Pero como alguien más dijo, recomendaría usar algo como jQuery en su lugar, ya que no todos los navegadores admiten DOM, y aquellos que tienen peculiaridades que se tratan internamente por bibliotecas JavaScript. Por ejemplo, jQuery se ve algo como esto:

$('#someID').html("<p>Hello, <b>World</b>!</p>");
 33
Author: Turnor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-06 14:43:47

La mejor manera de hacerlo es utilizar document.createTextNode. Una de las principales razones para usar esta función en lugar de innerHTML es que todo el escape de caracteres HTML se encargará de usted, mientras que tendría que escapar de su cadena usted mismo si simplemente estuviera configurando innerHTML.

 11
Author: Andrew Hare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-05 00:17:49

Puede obtener el mismo efecto manipulando el DOM. La forma más segura de cambiar el texto es eliminar todos los nodos secundarios del elemento y reemplazarlos con un nuevo nodo de texto.

var node = document.getElementById("one");

while( node.firstChild )
    node.removeChild( node.firstChild );
node.appendChild( document.createTextNode("Two") );

Eliminar los nodos secundarios elimina el contenido de texto de su elemento antes de reemplazarlo con el nuevo texto.

La razón por la que la mayoría de los desarrolladores evitan usar innerHTML es que el acceso a los elementos a través del DOM es compatible con los estándares.

 6
Author: Bill the Lizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-05 17:13:06

Si solo desea cambiar el texto plano, entonces hay una solución más rápida que se basa en los estándares:

document.getElementById("one").firstChild.data = "two";

De todos modos, tenga en cuenta que innerHTML va a ser parte del próximo estándar HTML 5.

 6
Author: Ionuț G. Stan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-05 17:25:43

Simple.

Sustitúyase text.innerHTML = 'two' por text.firstChild.nodeValue = 'two'.

 4
Author: BlackMagic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-30 23:50:04
var who=document.getElementById('one'), txt='new text';
if(who.innerText) who.innerText=txt;
else if(who.textContent) who.textContent= txt;

Esto puede ser tan objetable como innerHTML para usted, pero tiene la ventaja de trabajar en algunos casos (IE) donde innerHTML o appendChild no, como algunos nodos de tabla, el texto de los elementos de estilo y script y el valor de los campos de formulario

 2
Author: kennebec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-06 14:08:04

Puedes usar DOM de la siguiente manera:

<html>
<body>
<div>before</div>
<script type="text/javascript">
var element = document.getElementsByTagName("div")[0];
alert(element.firstChild.nodeValue);
element.removeChild(element.firstChild);
element.appendChild(document.createTextNode('after'));
alert(element.firstChild.nodeValue);
</script>
</body>

Pero creo que alguien rara vez hace esto, pero utiliza un marco como jQuery o Prototype o cualquier otro marco javascript allí en su lugar. Este es el ejemplo de jquery:

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
</head>
<body>
<div>before</div>
<script type="text/javascript">
var element = $("div");
alert(element.text());
element.text("after");
alert(element.text());
</script>
</body>
 1
Author: Sergej Andrejev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-05 00:30:55

Me parece que la combinación CSS + HTML + JS debería lograr los efectos deseados:

.myelement:before {   
    content: attr(alt);
} 

...

<span class='myelement' alt='initial value'></span> 

...

element.setAttribute('alt', 'new value'); 

¿Alguien sabe si esto funciona en la práctica?

 1
Author: ilya n.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-16 10:02:48

Bueno, si entiendo su pregunta correctamente, esta debería ser una respuesta.

var text = document.getElementById("one");
//text.innerHTML = "Two";
 text.childNodes[0].nodeValue="two";
 1
Author: Shamik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-24 07:54:02

También buscando una buena alternativa para evitar element.innerHTML Finalmente encontré esa solución:

HTMLElement.prototype.htmlContent = function(html)
{
    var dom = new DOMParser().parseFromString('<template>'+html+'</template>', 'text/html').head;
    this.appendChild(dom.firstElementChild.content);
}

//-- document.getElementById('my-id').innerHTML = string_of_html;
document.getElementById('my-id').htmlContent(string_of_html);

Otra alternativa sin etiquetas

HTMLElement.prototype.htmlContent = function(html)
{
    var dom = new DOMParser().parseFromString(html, 'text/html').body;
    while (dom.hasChildNodes()) this.appendChild(dom.firstChild);
}

Tenga en cuenta que este método realmente 'agrega' contenido cuando innerHTML 'reemplaza' contenido...

Esto puede ayudar:

HTMLElement.prototype.clearContent = function()
{
    while (this.hasChildNodes()) this.removeChild(this.lastChild);
}

//-- document.getElementById('my-id').innerHTML = '';
document.getElementById('my-id').clearContent();

Doc: https://github.com/swannty/escaping-innerHTML
perf: https://jsperf.com/escaping-innerhtml

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-07 21:59:03

A veces me resulta útil almacenar una referencia directa al nodo de texto si voy a actualizarlo regularmente. Hago algo como esto:

var dynamicText = myDiv.appendChild(document.createTextNode("the initial text"));

Y luego cada vez que necesito actualizarlo, simplemente hago esto:

dynamicText.nodeValue = "the updated text";

Esto evita tener que caminar por el DOM o agregar o quitar niños.

 0
Author: Code83,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-10 13:18:44