React.js: Встановіть innerHTML проти небезпечноSetInnerHTML


171

Чи є різниця "поза кадром" від встановлення внутрішньогоHTML елемента проти встановлення властивості небезпечноSetInnerHTML на елементі? Припустимо, що я належним чином дезінфікую речі заради простоти.

Приклад:

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

Я роблю щось трохи складніше, ніж наведений вище приклад, але загальна ідея та ж

Відповіді:


237

Так, є різниця!

Безпосередній ефект використання innerHTMLпорівняно з dangerouslySetInnerHTMLідентичним - вузол DOM оновиться введеним HTML.

Однак за лаштунками, коли ви користуєтесь dangerouslySetInnerHTMLцим, дає можливість реагувати, що HTML всередині цього компонента - це не те, що його хвилює.

Оскільки React використовує віртуальний DOM, коли він іде на порівняння відмінностей від фактичного DOM, він може випрямлювати обхід перевірки дітей цього вузла, оскільки знає, що HTML надходить з іншого джерела . Таким чином, є підвищення продуктивності.

Що ще важливіше , якщо ви просто використовуєте innerHTML, React не має можливості дізнатися, чи вузол DOM був змінений. Наступного разу, коли renderфункція буде викликана, React замінить вміст, який було введено вручну, тим, що, на його думку, має бути правильним стан цього вузла DOM.

Ваше рішення, яке слід використовувати componentDidUpdateзавжди для забезпечення синхронізації вмісту, я вважаю, що це спрацює, але під час кожного візуалізації може виникнути спалах.


11
Я написав невеликий, ненауковий тест на парф, щоб показати різницю між вбудованим SVG та використанням dangerouslySetInnerHTML: webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - вимикає метод внутрішнього HTML майже вдвічі швидше (див. Консоль на веб-пакунку)
Джоша

4
Це вірно і легко передбачити. Оскільки innerHTML - це власний метод, який пов'язує SVG-код безпосередньо з DOM, не враховуючи нічого. З іншого боку, небезпечноSetInnerHTML - це метод, що походить від React, що SVG-код повинен бути проаналізований як діти React Component, перш ніж розмістити їх у віртуальний DOM, а потім надати DOM.
Up209d

3

Згідно з небезпечно встановленими внутрішніми HTMLML ,

Неправильне використання кані innerHTMLможе відкрити вас до нападу міжсайтових сценаріїв (XSS) . Санітизація даних користувачів для відображення є, як відомо, схильною до помилок, а невдача належним чином оздоровитись - одна з провідних причин вразливості веб-сторінок в Інтернеті.

Наша філософія дизайну полягає в тому, що робити "речі" безпечно, а розробники повинні чітко заявляти про свої наміри під час виконання "небезпечних" операцій. Ім’я опори dangerouslySetInnerHTMLнавмисно вибрано як лякаюче, а значення опори (об'єкт замість рядка) може використовуватися для позначення даних, що санітуються.

Після повного розуміння наслідків безпеки та належної дезінфекції даних, створіть новий об'єкт, що містить лише ключ __htmlта ваші санітарні дані як значення. Ось приклад використання синтаксису JSX:

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

<div dangerouslySetInnerHTML={createMarkup()} /> 

Детальніше про це читайте за посиланням нижче:

документація : Реагувати елементи DOM - небезпечноSetInnerHTML .


1
Це не відповідає на запитання.
Квентін

2

На основі ( небезпечноSetInnerHTML ).

Це опора, яка робить саме те, що ви хочете. Однак вони називають це, щоб переконатися, що використовувати його слід обережно


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