Альтернатива для внутреннего HTML?
-
23-08-2019 - |
Вопрос
Мне интересно, есть ли способ изменить текст чего-либо в HTML без использования InnerHTML.
Причина, по которой я спрашиваю, заключается в том, что W3C не одобряет это.Я знаю, что это придирки, но я просто хочу знать, есть ли способ?
РЕДАКТИРОВАТЬ:люди, кажется, неправильно понимают, о чем я здесь спрашиваю:Я хочу найти способ эффективно изменить отображаемый текст.
Если бы у меня был:
<div id="one">One</a>
InternalHTML позволяет мне сделать это:
var text = document.getElementsById("one");
text.innerHTML = "Two";
И текст на моем экране изменится.
Я не хочу добавлять больше текста, я хочу изменить уже существующий текст.
Решение
Рекомендуемый способ — манипулирование 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.
РЕДАКТИРОВАТЬ
В ответ на ваше редактирование, чтобы заменить текущий контент, вы просто удаляете существующий контент, а затем используете приведенный выше код для заполнения нового контента.Например:
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>");
Другие советы
Лучший способ сделать это - использовать document.createTextNode
.Одна из основных причин использования этой функции вместо innerHTML
заключается в том, что все экранирование символов HTML будет выполнено за вас, тогда как вам пришлось бы экранировать строку самостоятельно, если бы вы просто устанавливали innerHTML
.
Вы можете получить тот же эффект, манипулируя DOM.Самый безопасный способ изменить текст — удалить все дочерние узлы элемента и заменить их новым текстовым узлом.
var node = document.getElementById("one");
while( node.firstChild )
node.removeChild( node.firstChild );
node.appendChild( document.createTextNode("Two") );
Удаление дочерних узлов избавляет от текстового содержимого вашего элемента перед заменой его новым текстом.
Причина, по которой большинство разработчиков избегают использования InnerHTML, заключается в том, что доступ к элементам через DOM соответствует стандартам.
Если вы хотите изменить только простой текст, есть более быстрое решение, основанное на стандартах:
document.getElementById("one").firstChild.data = "two";
В любом случае, обратите внимание, что InternalHTML станет частью будущего стандарта HTML 5.
Простой.
Заменять text.innerHTML = 'two'
с text.firstChild.nodeValue = 'two'
.
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 не работают, например, некоторые узлы таблицы, текст элементов стиля и сценария, а также значения полей формы.
Вы можете использовать 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 или Опытный образец или любой другой фреймворк JavaScript там вместо.Это пример 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>
Мне кажется, что комбинация CSS+HTML+JS должна достичь желаемых эффектов:
.myelement:before {
content: attr(alt);
}
...
<span class='myelement' alt='initial value'></span>
...
element.setAttribute('alt', 'new value');
Кто-нибудь знает, работает ли это на практике?
Ну, если я правильно понимаю ваш вопрос, это должен быть ответ.
var text = document.getElementById("one");
//text.innerHTML = "Two";
text.childNodes[0].nodeValue="two";
Тоже ищу хорошую альтернативу обходу 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);
Другая альтернатива без тегов <template>, но вместо этого использовать цикл:
HTMLElement.prototype.htmlContent = function(html)
{
var dom = new DOMParser().parseFromString(html, 'text/html').body;
while (dom.hasChildNodes()) this.appendChild(dom.firstChild);
}
Имейте в виду, что этот метод фактически «добавляет» контент, когда внутренний HTML «заменяет» контент...
Это может помочь:
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
Иногда мне кажется полезным сохранить прямую ссылку на текстовый узел, если я собираюсь регулярно его обновлять.Я делаю что-то вроде этого:
var dynamicText = myDiv.appendChild(document.createTextNode("the initial text"));
И затем всякий раз, когда мне нужно его обновить, я просто делаю это:
dynamicText.nodeValue = "the updated text";
Это избавляет от необходимости проходить по DOM, добавлять или удалять дочерние элементы.
InsertAdjacentHTML() — лучший вариант.Читать далее:Нажмите, чтобы просмотреть документацию