2009-04-05 2 views
28

Мне интересно, есть ли способ изменить текст чего-либо в HTML без использования innerHTML.Альтернатива для innerHTML?

Причина, о которой я прошу, заключается в том, что она нахмурилась W3C. Я знаю, что это ничто, но я просто хочу знать, есть ли способ?

EDIT: люди, похоже, неправильно понимают, что я прошу здесь: я хочу найти способ эффектно изменить отображаемый текст.

Если у меня есть:

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

innerHTML позволяет мне это сделать:

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

И текст на моем экране будет изменен.
Я не хочу добавлять больше текста, я хочу изменить все уже существующий текст.

+6

FYI: innerHTML экстремально быстрее по сравнению использовать DOM createElement, createTextNode и т.д. Efficency соображением: http://www.quirksmode.org/dom/ innerhtml.html Кроме того, innerHTML является частью HTML5! –

+0

@Marco, что вы имеете в виду, когда говорите, что innerHTML является частью HTML5? – Pacerier

+0

@Pacerier: innerHTML работает во всех браузерах, но не является частью стандартов W3C HTML4.1 (и WebDevHobo говорит, что это не одобряется). В то время как innerHTML должен быть частью HTML5: http://www.w3.org/TR/2011/WD-html5-diff-20110113/#htmldocument-extensions –

ответ

29

Рекомендуемый способ - с помощью манипуляций с DOM, но он может быть довольно многословным. Например:

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

В ответ на ваши изменения, чтобы заменить текущее содержимое, вы просто удалить существующее содержимое, а затем использовать код выше, чтобы заполнить новое содержание. Например:

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

Но, как кто-то сказал, я бы рекомендовал использовать что-то вроде JQuery вместо этого, так как не все браузеры полностью поддерживают DOM, а те, что есть причуды, которые рассматриваются внутренне библиотеками JavaScript. Например, JQuery выглядит примерно так:

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

так на самом деле, сначала разместите новый текст, а затем удалите старый ... что кажется очень длинным способом делать что-то ... Интересно, почему W3C не одобряет innerHTML – KdgDev

+2

Другой способ: Их мнение таково: innerHTML, можно вставить недопустимую разметку в документ XML/XHTML. Хотя, как говорится, они, похоже, передумали с HTML5. – Turnor

+12

jQuery использует innerHTML много раз внутри кода, предлагая использовать jQuery, чтобы избежать использования innerHTML, не имеет большого смысла ИМХО. –

10

Лучший способ сделать это - использовать document.createTextNode. Одной из основных причин использования этой функции вместо innerHTML является то, что все экранирование HTML-символов будет позаботиться о вас, тогда как вы должны были бы избежать своей строки самостоятельно, если бы вы просто установили innerHTML.

+3

Однако, кажется, что innerHTML намного быстрее, чем методы W3C DOM: http://www.quirksmode.org/dom/innerhtml.html. –

+3

Это зависит от того, что вы делаете; неверно сказать, что один метод лучше одевается. DOM имеет тенденцию замедляться при выполнении операций списка дочерних узлов на множестве элементов (стремящихся к O (n²)), где innerHTML может делать их все сразу. Но шаг inHTML по синтаксическому анализу/сериализации может сделать другие операции медленнее. – bobince

1

Вы можете использовать DOM следующим образом:

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

Но я думаю, что кто-то редко это сделать, но использовать рамки как jQuery или Prototype или любой другой Javascript рамочном out there вместо. Это пример 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

Вы можете получить тот же эффект, манипулируя DOM. Самый безопасный способ изменения текста - удалить все дочерние узлы этого элемента и заменить их новым текстовым узлом.

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

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

Удаление дочерних узлов устраняет текстовое содержимое элемента перед заменой его новым текстом.

Причина, по которой большинство разработчиков избегает использования innerHTML, заключается в том, что доступ к элементам через DOM соответствует стандартам.

6

Если вы хотите изменить только простой текст, то есть более быстрое решение, которое опирается на стандарты:

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

Во всяком случае, обратите внимание, что innerHTML собирается быть частью будущего стандарта HTML 5.

+0

Это работает только в том случае, если уже есть дочерний узел. –

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

Это может быть столь же нежелательно, как innerHTML для вас, но он имеет преимущество работы в некоторых случаях (IE), где innerHTML или AppendChild не, как некоторые узлы таблицы, текст стилей и сценарии элементов и значение полей формы

1

мне кажется, что CSS + HTML + JS сочетание должно достичь желаемых эффектов:

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

... 

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

... 

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

кто-нибудь знает, если это работает на практике?

4

Простой.

Заменить text.innerHTML = 'two' на text.firstChild.nodeValue = 'two'.

+1

Да! И [в 20 раз быстрее] (http://stackoverflow.com/a/18418270/287948)! –

1

Ну, я правильно понимаю ваш вопрос, это должен быть ответ.

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

Иногда мне удобно хранить прямую ссылку на текстовый узел, если я собираюсь регулярно его обновлять. Я делаю что-то вроде этого:

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

А потом, когда мне нужно обновить его, я просто делаю это:

dynamicText.nodeValue = "the updated text"; 

Это избавляет от необходимости ходить DOM добавить или удалить какие-либо детей.

1

ищет Кроме того, для хорошей альтернативой, чтобы обойти element.innerHTML я наконец-то нашел, что решение:

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

Другой вариант без < шаблон > теги, но цикл вместо:

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

Имейте в виду, что это метод фактически «добавляет» содержимое, когда innerHTML «заменяет» контент ...

Это может помочь:

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

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

документ: https://github.com/swannty/escaping-innerHTML
перфорация: https://jsperf.com/escaping-innerhtml

Смежные вопросы