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

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

Jshoe523
источник

Ответы:

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