React.js: установить innerHTML против опасного SetInnerHTML


172

Есть ли какое-то "закулисное" отличие от установки элемента innerHTML против установки свойства dangerouslySetInnerHTML для элемента? Предположим, я правильно дезинфицирую вещи ради простоты.

Пример:

var test = React.createClass({
  render: function(){
    return (
      <div contentEditable='true' dangerouslySetInnerHTML={{ __html: "Hello" }}></div>
    );
  }
});

против

var test = React.createClass({
  componentDidUpdate: function(prevProp, prevState){
    this.refs.test.innerHTML = "Hello";
  },
  render: function(){
    return (
      <div contentEditable='true' ref='test'></div>
    );
  }
});

Я делаю что-то более сложное, чем приведенный выше пример, но общая идея та же

Ответы:


238

Да, есть разница!

Непосредственный эффект использования innerHTMLvs. dangerouslySetInnerHTMLидентичен - узел DOM обновится с введенным HTML.

Однако за кулисами, когда вы используете dangerouslySetInnerHTMLего, React знает, что HTML внутри этого компонента не то, о чем он заботится.

Поскольку React использует виртуальный DOM, когда он сравнивает diff с фактическим DOM, он может обойти проверку дочерних узлов этого узла, поскольку он знает, что HTML-код поступает из другого источника . Так что есть повышение производительности.

Что еще более важно , если вы просто используете innerHTML, React не сможет узнать, был ли изменен узел DOM. В следующий раз, когда renderфункция будет вызвана, React перезапишет содержимое, которое было введено вручную, с тем, что, по его мнению, должно быть правильным состоянием этого узла DOM.

componentDidUpdateЯ считаю, что ваше решение использовать для обеспечения синхронизации контента всегда будет работать, но при каждом рендеринге может возникать вспышка.


11
Я написал небольшой ненаучный перф тест, чтобы показать разницу между встраиванием SVG и использованием dangerouslySetInnerHTML: webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - настраивает метод innerHTML почти в два раза быстрее (см. Консоль в webpackbin)
Йоша

4
Это правда и легко предсказать. Так как innerHTML является нативным методом, который связывает код SVG напрямую с DOM, не рассматривая ничего. С другой стороны, dangerouslySetInnerHTML - это метод, полученный из React, для того, чтобы SVG-код нужно было проанализировать как дочерние компоненты React, прежде чем поместить их в виртуальный DOM и затем отобразить в DOM.
Up209d

3

Согласно Опасно указанному innerHTML ,

Неправильное использование innerHTMLможет открыть вас для атаки межсайтового скриптинга (XSS) . Обеззараживание пользовательского ввода для отображения, как известно, подвержено ошибкам, а отсутствие надлежащей дезинфекции является одной из основных причин веб-уязвимостей в Интернете.

Наша философия проектирования заключается в том, что сделать вещи безопасными должно быть «легко», и разработчики должны четко указать свое намерение при выполнении «небезопасных» операций. Название реквизита dangerouslySetInnerHTMLнамеренно выбрано как пугающее, и значение реквизита (объект вместо строки) можно использовать для обозначения очищенных данных.

После полного понимания последствий для безопасности и правильной очистки данных создайте новый объект, содержащий в качестве значения только ключ __htmlи ваши очищенные данные. Вот пример использования синтаксиса JSX:

function createMarkup() {
    return {
       __html: 'First &middot; Second'    };
 }; 

<div dangerouslySetInnerHTML={createMarkup()} /> 

Узнайте больше об этом, используя ссылку ниже:

Документация : Реагировать на DOM Elements - опасно SetInnerHTML .


1
Это не отвечает на вопрос.
Квентин

2

Основано на ( опасно SetInnerHTML ).

Это опора, которая делает именно то, что вы хотите. Однако они называют его, чтобы передать, что его следует использовать с осторожностью


1
хорошо согласно документам кажется, что это единственная причина, все еще запутанная
mkb
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.