2009-04-05 22 views
28

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

La razón que estoy preguntando es porque está algo mal visto por el W3C. Sé que es quisquilloso, pero solo quiero saber, ¿hay alguna manera?

EDITAR: la gente parece entender mal lo que estoy preguntando aquí: Quiero encontrar una manera de modificar 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 deseo agregar más texto, deseo cambiar el texto ya existente.

+6

FYI: innerHTML es extremadamente rápido en comparación con el uso de DOM createElement, createTextNode, etc. Eficiencia consideración: http://www.quirksmode.org/dom/ innerhtml.html ¡Además innerHTML es parte de HTML5! –

+0

@Marco ¿Qué quieres decir cuando dices innerHTML es parte de HTML5? – Pacerier

+0

@Pacerier: innerHTML funciona en todos los navegadores, pero no forma parte de los estándares W3C HTML4.1 (y WebDevHobo dice que no está bien visto). Se supone que innerHTML es parte de HTML5: http://www.w3.org/TR/2011/WD-html5-diff-20110113/#htmldocument-extensions –

Respuesta

29

La forma recomendada es a través de la manipulación DOM, pero puede ser bastante detallado. 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, con el fin de sustituir el contenido actual, sólo tiene que quitar el contenido existente, a continuación, utiliza el código anterior para rellenar 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 ha dicho, me gustaría recomendar el uso de algo como jQuery lugar, ya que no todos los navegadores soportan plenamente DOM, y los que tienen peculiaridades que son tratadas internamente por las bibliotecas de JavaScript. Por ejemplo, jQuery es como la siguiente:

$('#someID').html("<p>Hello, <b>World</b>!</p>"); 
+0

así que en realidad, primero coloque el texto nuevo y luego elimine el anterior ... esa parece una forma muy larga de hacer las cosas ... Me pregunto por qué el W3C no aprueba innerHTML – KdgDev

+2

Otra forma :) Su opinión es que con innerHTML, es posible insertar marcas no válidas en un documento XML/XHTML. Aunque dicho eso, parece que han cambiado de opinión con HTML5. – Turnor

+12

jQuery usa innerHTML muchas veces dentro del código, por lo que sugiere usar jQuery para evitar el uso de innerHTML no tiene mucho sentido en mi humilde opinión. –

10

La mejor manera de hacerlo es usar document.createTextNode. Una de las principales razones para usar esta función en lugar de innerHTML es que todo el carácter HTML que se está escapando se ocupará de usted, mientras que usted mismo tendría que escapar de la cadena si estuviera simplemente configurando innerHTML.

+3

Sin embargo, parece que innerHTML es mucho más rápido que los métodos W3C DOM: http://www.quirksmode.org/dom/innerhtml.html. –

+3

Depende de lo que esté haciendo; es engañoso decir que un método es mejor. DOM tiende a ralentizarse cuando se hacen operaciones de lista de ChildNode en muchos elementos (que tienden a O (n²)), donde innerHTML puede hacerlos todos a la vez. Pero el paso de serialización/análisis interno de innerHTML puede hacer que otras operaciones sean más lentas. – bobince

1

Usted podría utilizar 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 yo creo que nadie rara vez hacer esto pero el uso de un marco como jQuery o Prototype o cualquier otro marco Javascript fuera de there en su lugar. Este es un 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> 
6

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

Al eliminar los nodos secundarios se elimina el contenido de texto de su elemento antes de reemplazarlo con el nuevo texto.

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

6

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

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

De todos modos, tenga en cuenta que innerHtml va a ser parte de la próxima HTML 5 estándar.

+0

Eso solo funciona si ya hay un nodo infantil. –

2
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 desagradable tan innerHTML para usted, pero tiene la ventaja de trabajar en algunos casos (IE), donde innerHTML o appendChild no lo hacen, al igual que algunos nodos de tabla, el texto de los elementos de estilo y de la escritura y el valor de los campos de formulario

1

me parece que la combinación de CSS + HTML + JS debe 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?

4

Simple.

Reemplazar text.innerHTML = 'two' con text.firstChild.nodeValue = 'two'.

+1

¡Sí! Y [es 20 veces más rápido] (http://stackoverflow.com/a/18418270/287948)! –

1

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"; 
0

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 entonces cada vez que necesito para actualizarlo, acabo de hacer esto:

dynamicText.nodeValue = "the updated text"; 

Esto evita tener que recorrer el DOM o añadir o eliminar cualquier niño.

1

También en busca de una buena alternativa para eludir element.innerHTML Finalmente encontré que la 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 <plantilla> etiquetas, pero bucle en su lugar:

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 en realidad 'agregar' contenido cuando innerHTML 'reemplazar' 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
Potencia: https://jsperf.com/escaping-innerhtml