2009-04-05 8 views
28

Zastanawiam się, czy istnieje sposób na zmianę tekstu czegokolwiek w HTML bez użycia innerHTML.Alternatywa dla innerHTML?

Powód, o który proszę, ponieważ jest trochę mile zaskoczony przez W3C. Wiem, że to nitpicking, ale chcę tylko wiedzieć, czy istnieje sposób?

EDYCJA: ludzie nie rozumieją tego, o co tutaj pytam: chcę znaleźć sposób na skuteczną zmianę wyświetlanego tekstu.

Jeśli mam:

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

innerHTML pozwala mi to zrobić:

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

a tekst na ekranie będzie się zmieniły.
Nie chcę dodawać więcej tekstu, chcę zmienić już istniejący tekst.

+6

FYI: innerHTML jest wyjątkowo szybciej w porównaniu do korzystania DOM createElement, createTextNode itp Efficency rozpatrzenie: http://www.quirksmode.org/dom/ innerhtml.html Ponadto innerHTML jest częścią HTML5! –

+0

@Marco co masz na myśli mówiąc, że innerHTML jest częścią HTML5? – Pacerier

+0

@Pacerier: innerHTML działa we wszystkich przeglądarkach, ale nie jest częścią standardów W3C HTML4.1 (a WebDevHobo twierdzi, że jest na tym zmarsz czoło). Whilest innerHTML ma być częścią HTML5: http://www.w3.org/TR/2011/WD-html5-diff-20110113/#htmldocument-extensions –

Odpowiedz

29

Zalecany sposób polega na manipulacji DOM, ale może być dość szczegółowy. Na przykład:

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

EDIT

W odpowiedzi na Twój edycji, w celu zastąpienia bieżącej zawartości, po prostu usunąć istniejącą zawartość, a następnie użyć kodu powyżej wypełnić nową treścią. Na przykład:

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

Ale jak ktoś inny powiedział, polecam użyciu coś jak jQuery zamiast, jak nie wszystkie przeglądarki obsługują DOM w pełni, a te, które mają dziwactwa, które są przedmiotem wewnętrznie przez biblioteki JavaScript. Na przykład, jQuery wygląda mniej więcej tak:

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

więc tak naprawdę, najpierw umieść nowy tekst, a następnie usuń stare ... to wydaje się bardzo długi sposób robienia rzeczy ... Zastanawiam się, dlaczego W3C nie akceptuje innerHTML – KdgDev

+2

W inny sposób :) Ich zdaniem jest to innerHTML, możliwe jest wstawienie nieprawidłowych znaczników do dokumentu XML/XHTML. Mimo tego, jak się wydaje, zmieniły zdanie dzięki HTML5. – Turnor

+12

jQuery używa innerHTML wiele razy wewnątrz kodu, sugerując użycie jQuery, aby uniknąć użycia innerHTML, nie ma sensu IMHO. –

10

Lepszym sposobem na to jest użycie document.createTextNode. Jednym z głównych powodów korzystania z tej funkcji zamiast z innerHTML jest to, że wszystkie znaki ucieczki do postaci HTML zostaną za ciebie zadbane, podczas gdy sam musisz uciec z twojej struny, jeśli po prostu ustawisz innerHTML.

+3

Wydaje się jednak, że innerHTML jest znacznie szybszy niż metody DOM W3C: http://www.quirksmode.org/dom/innerhtml.html. –

+3

Zależy od tego, co robisz; to mylące powiedzieć, że jedna metoda jest lepsza. DOM ma tendencję do spowalniania podczas wykonywania operacji na listach potomnych na wielu elementach (z tendencją do O (n²)), gdzie innerHTML może je wszystkie naraz. Ale krok parsowania/serializacji innerHTML może spowolnić inne operacje. – bobince

1

Można użyć DOM następująco:

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

Ale myślę, że ktoś rzadko to zrobić, ale używać ramy jak jQuery lub Prototype lub innego javascript ramowej zamiast tego jest there. To jest przykład 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

Możesz uzyskać ten sam efekt, manipulując DOM. Najbezpieczniejszym sposobem zmiany tekstu jest usunięcie wszystkich węzłów potomnych elementu i zastąpienie ich nowym węzłem tekstowym.

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

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

Usunięcie węzłów potomnych eliminuje zawartość tekstową elementu przed zastąpieniem go nowym tekstem.

Powodem, dla którego większość programistów unika używania innerHTML, jest to, że dostęp do elementów przez DOM jest zgodny ze standardami.

6

Jeśli chcesz tylko zmienić zwykły tekst, to nie jest to szybsze rozwiązanie, które opiera się na normach:

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

W każdym razie należy pamiętać, że innerHTML będzie częścią nadchodzącego standardu HTML 5.

+0

Działa to tylko wtedy, gdy istnieje już węzeł potomny. –

2
var who=document.getElementById('one'), txt='new text'; 
if(who.innerText) who.innerText=txt; 
else if(who.textContent) who.textContent= txt; 

To może być przyjęte za innerHTML do ciebie, ale ma tę zaletę, że działa w niektórych przypadkach (IE), gdzie innerHTML lub appendChild nie, tak jak w niektórych węzłach stołowych tekście elementy stylu i skrypt i wartość pola formularza

1

wydaje mi się, że CSS + HTML + JS kombinacja powinna osiągnąć pożądane efekty:

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

... 

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

... 

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

czy ktoś wie czy to działa w praktyce?

4

Prosty.

Wymień text.innerHTML = 'two' na text.firstChild.nodeValue = 'two'.

+1

Tak! I [jest 20x szybciej] (http://stackoverflow.com/a/18418270/287948)! –

1

Cóż, dobrze rozumiem twoje pytanie, to powinna być odpowiedź.

var text = document.getElementById("one"); 
//text.innerHTML = "Two"; 
text.childNodes[0].nodeValue="two"; 
0

czasami znaleźć przydatne do przechowywania bezpośrednie odniesienie do węzła tekstowego, jeśli idę do aktualizowania go regularnie. I zrobić coś takiego:

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

A potem, kiedy muszę je zaktualizować, po prostu to zrobić:

dynamicText.nodeValue = "the updated text"; 

Zapobiega to konieczności chodzić DOM lub dodawać lub usuwać żadnych dzieci.

1

patrząc również na dobrą alternatywę ominąć element.innerHTML I w końcu okazało się, że rozwiązanie:

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

Inną alternatywą bez <szablon> znaczniki, ale pętla Zamiast:

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

pamiętać, że ta metoda faktycznie "dodaje" zawartość, gdy innerHTML "zastępuje" treść ...

Może to pomóc:

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