Какие есть альтернативы document.write? - PullRequest
59 голосов
/ 27 декабря 2010

В уроках я научился использовать document.write. Теперь я понимаю, что многие это осуждают. Я пробовал print(), но потом буквально отправляет его на принтер.

Так, какие альтернативы я должен использовать, и почему я не должен использовать document.write? Как в школах, так и в школах MDN используется document.write.

Ответы [ 10 ]

69 голосов
/ 17 декабря 2014

Причина, по которой ваш HTML заменен, заключается в неправильной функции JavaScript: document.write().

Это определенно "плохая форма". Он работает только с веб-страницами, если вы используете его при загрузке страницы; и если вы используете его во время выполнения, он заменит весь ваш документ с вводом. И если вы применяете его как строгую структуру XHTML, это даже не допустимый код.


проблема:

document.write записывает в поток документов. Вызов document.write для закрытого (или загруженного) документа автоматически вызывает document.open, что приведет к очистке документа.

- цитата из MDN

document.write() имеет двух приспешников, document.open() и document.close(). Когда документ HTML загружается, документ «открыт». Когда документ завершит загрузку, документ «закроется». Использование document.write() на этом этапе сотрет весь ваш (закрытый) документ HTML и заменит его новым (открытым ) документ. Это означает, что ваша веб-страница стерла себя и начала писать новую страницу - с нуля.

Я полагаю, document.write() также приводит к снижению производительности браузера (поправьте меня, если я ошибаюсь).


пример:

В этом примере записывается вывод в документ HTML после загрузки страницы. Наблюдайте, как злые силы document.write() очищают весь документ, когда вы нажимаете кнопку «уничтожить»:

I am an ordinary HTML page.  I am innocent, and purely for informational purposes. Please do not <input type="button" onclick="document.write('This HTML page has been succesfully exterminated.')" value="exterminate"/>
me!

альтернативы:

  • .innerHTML Это прекрасная альтернатива, но этот атрибут должен быть прикреплен к элементу, в который вы хотите поместить текст.

Пример: document.getElementById('output1').innerHTML = 'Some text!';

  • .createTextNode() - это альтернатива, рекомендованная W3C .

Пример: var para = document.createElement('p'); para.appendChild(document.createTextNode('Hello, '));

ПРИМЕЧАНИЕ. Известно, что это приводит к некоторому снижению производительности (медленнее, чем .innerHTML). Я рекомендую использовать .innerHTML вместо.


пример с альтернативой .innerHTML:

I am an ordinary HTML page. 
I am innocent, and purely for informational purposes. 
Please do not 
<input type="button" onclick="document.getElementById('output1').innerHTML = 'There was an error exterminating this page. Please replace <code>.innerHTML</code> with <code>document.write()</code> to complete extermination.';" value="exterminate"/>
 me!
<p id="output1"></p>
22 голосов
/ 04 ноября 2013

Вот код, который должен заменить document.write на месте:

document.write=function(s){
    var scripts = document.getElementsByTagName('script');
    var lastScript = scripts[scripts.length-1];
    lastScript.insertAdjacentHTML("beforebegin", s);
}
11 голосов
/ 27 декабря 2010

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

9 голосов
/ 21 ноября 2012

Просто добавив здесь примечание, чтобы сказать, что, хотя использование document.write вызывает неодобрение из-за проблем производительности (синхронный ввод и оценка DOM), также есть без фактического 1: 1 альтернатива , если вы используете document.write для добавления тегов скрипта по требованию.

Есть много отличных способов избежать этого (например, загрузчики скриптов, такие как RequireJS , которые управляют вашими цепочками зависимостей), но они более инвазивны и поэтому лучше всего используются на всем протяжении сайт / приложение.

7 голосов
/ 27 декабря 2010

Вопрос зависит от того, что вы на самом деле пытаетесь сделать.

Обычно вместо document.write можно использовать someElement.innerHTML или лучше, document.createElement с someElement.appendChild.

Вы также можете рассмотреть возможность использования библиотеки, такой как jQuery, и использования там функций модификации: http://api.jquery.com/category/manipulation/

5 голосов
/ 19 апреля 2013

Вероятно, это самая правильная прямая замена: insertAdjacentHTML .

3 голосов
/ 27 декабря 2010

Попробуйте использовать getElementById () или getElementsByName () для доступа к конкретному элементу, а затем использовать свойство innerHTML:

<html>
    <body>
        <div id="myDiv1"></div>
        <div id="myDiv2"></div>
    </body>

    <script type="text/javascript">
        var myDiv1 = document.getElementById("myDiv1");
        var myDiv2 = document.getElementById("myDiv2");

        myDiv1.innerHTML = "<b>Content of 1st DIV</b>";
        myDiv2.innerHTML = "<i>Content of second DIV element</i>";
    </script>
</html>
2 голосов
/ 12 августа 2016

Вы можете объединить insertAdjacentHTML метод и document.currentScript свойство.

Метод insertAdjacentHTML() интерфейса Element анализирует указанный текст как HTML или XML и вставляет результирующие узлы в дерево DOM в указанной позиции :

  • 'beforebegin': перед самим элементом.
  • 'afterbegin': только внутри элемента, перед его первым потомком.
  • beforeend: только внутри элемента, после его последнего потомка.
  • 'afterend': после самого элемента.

Свойство Document.currentScript возвращает элемент <script>, сценарий которого в данный момент обрабатывается. Лучшая позиция будет до начала - новый HTML будет вставлен до самого <script>.

<script>
  document.currentScript.insertAdjacentHTML(
    'beforebegin', 
    'this is the document.write alternative'
);
</script>
2 голосов
/ 02 ноября 2015

Я не вижу проблемы с document.write. Если вы используете его до того, как сработает событие onload, как вы, вероятно, предполагаете, для построения элементов, например, из структурированных данных, это подходящий инструмент для использования. Нет никакого преимущества в производительности при использовании insertAdjacentHTML или явном добавлении узлов в DOM после его построения. Я только что проверил три различных способа со старым сценарием, который однажды использовал для планирования входящих вызовов модемов для круглосуточной услуги на банке из 4 модемов.

К моменту завершения этот скрипт создает более 3000 узлов DOM, в основном ячеек таблицы. На 7-летнем ПК, на котором установлен Firefox в Vista, это небольшое упражнение занимает менее 2 секунд, используя document.write из локального исходного файла размером 12 КБ и три 1-пиксельных GIF-файла, которые повторно используются около 2000 раз. Страница просто появляется полностью сформированной, готовой к обработке событий.

Использование insertAdjacentHTML не является прямой заменой, поскольку браузер закрывает теги, которые, как требуется сценарию, остаются открытыми, и занимает в два раза больше , чтобы в конечном итоге создать искаженную страницу. Запись всех фрагментов в строку, а затем передача ее в insertAdjacentHTML занимает еще больше времени, но, по крайней мере, вы получаете страницу, как задумано. Другие варианты (например, ручное восстановление DOM по одному узлу за раз) настолько нелепы, что я даже не собираюсь туда идти.

Иногда document.write - это то, что нужно использовать. Тот факт, что это один из самых старых методов в JavaScript, - это не точка зрения против него, а точка зрения в его пользу - это высокооптимизированный код, который делает именно то, для чего он предназначался, и делал с самого начала.

Приятно знать, что существуют альтернативные методы после загрузки, но следует понимать, что они предназначены для совершенно другой цели; а именно изменение DOM после его создания и выделения памяти для него. Использование этих методов по своей природе более ресурсоемко, если ваш сценарий предназначен для написания HTML-кода, из которого браузер в первую очередь создает DOM.

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

PS: Я только что протестировал использование параметра onload в теге body, и даже на этом этапе документ все еще open и document.write() функционирует, как предполагалось. Кроме того, нет никакой ощутимой разницы в производительности между различными методами в последней версии Firefox. Конечно, где-то в аппаратном / программном стеке существует тонна кеширования, но в этом-то и дело - пусть машина выполняет свою работу. Это может иметь значение на дешевом смартфоне, хотя. Ура!

0 голосов
/ 09 ноября 2015

Я не уверен, что это будет работать точно, но я подумал о

var docwrite = function(doc) {               
    document.write(doc);          
};

Это решило проблему с сообщениями об ошибках для меня.

...