React.js: Ustaw innerHTML vs dangerousouslySetInnerHTML


171

Czy jest jakaś różnica „za kulisami” między ustawieniem internalHTML elementu a ustawieniem właściwości niebezpiecznejSetInnerHTML elementu? Załóżmy, że odpowiednio odkażam rzeczy ze względu na prostotę.

Przykład:

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

vs

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

Robię coś bardziej skomplikowanego niż powyższy przykład, ale ogólny pomysł jest taki sam

Odpowiedzi:


237

Tak, jest różnica!

Bezpośredni efekt użycia innerHTMLversus dangerouslySetInnerHTMLjest identyczny - węzeł DOM zaktualizuje się o wstrzyknięty HTML.

Jednak za kulisami, kiedy dangerouslySetInnerHTMLgo używasz , pozwala Reactowi wiedzieć, że HTML wewnątrz tego komponentu nie jest czymś, na czym mu zależy.

Ponieważ React używa wirtualnego DOM, kiedy chce porównać różnice z rzeczywistym DOM, może od razu ominąć sprawdzanie elementów potomnych tego węzła, ponieważ wie, że HTML pochodzi z innego źródła . Więc jest wzrost wydajności.

Co ważniejsze , jeśli po prostu używasz innerHTML, React nie ma możliwości dowiedzenia się, że węzeł DOM został zmodyfikowany. Następnym razem, gdy renderfunkcja zostanie wywołana, React nadpisze zawartość, która została ręcznie wstrzyknięta, tym, co uważa za prawidłowy stan tego węzła DOM.

Twoje rozwiązanie, które componentDidUpdatema zawsze zapewnić synchronizację zawartości. Uważam, że zadziała, ale podczas każdego renderowania może pojawić się błysk.


11
Napisałem mały, nienaukowy test wydajności, aby pokazać różnicę między wstawianiem SVG a użyciem dangerouslySetInnerHTML: webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - dostrajanie metody innerHTML jest prawie dwukrotnie szybsze (patrz konsola w pakiecie internetowym)
Joscha

4
To prawda i łatwo przewidzieć. Ponieważ innerHTML jest natywną metodą, która wiąże kod SVG bezpośrednio z DOM, bez uwzględniania niczego. Z drugiej strony, dangerousouslySetInnerHTML to metoda pochodząca z React, zgodnie z którą kod SVG musi zostać przeanalizowany jako elementy potomne komponentu React przed umieszczeniem go w wirtualnym DOM, a następnie renderowaniem do DOM.
Up209d

3

Według Dangerously Set innerHTML ,

Niewłaściwe użycie innerHTMLmoże narazić Cię na atak cross-site scripting (XSS) . Oczyszczanie danych wprowadzanych przez użytkownika na potrzeby wyświetlania jest notorycznie podatne na błędy, a niepowodzenie w prawidłowym oczyszczaniu jest jedną z głównych przyczyn luk w zabezpieczeniach sieci Web w Internecie.

Nasza filozofia projektowania zakłada, że ​​zapewnienie bezpieczeństwa powinno być „łatwe”, a programiści powinni wyraźnie określić swoje zamiary podczas wykonywania „niebezpiecznych” operacji. Nazwa dangerouslySetInnerHTMLwłaściwości została celowo wybrana jako przerażająca, a wartość właściwości (obiekt zamiast ciągu znaków) może służyć do wskazania oczyszczonych danych.

Po pełnym zrozumieniu konsekwencji związanych z bezpieczeństwem i prawidłowym __htmloczyszczeniu danych utwórz nowy obiekt zawierający tylko klucz i oczyszczone dane jako wartość. Oto przykład wykorzystujący składnię JSX:

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

<div dangerouslySetInnerHTML={createMarkup()} /> 

Przeczytaj więcej na ten temat, korzystając z poniższego linku:

dokumentacja : React DOM Elements - dangerousouslySetInnerHTML .


1
To nie odpowiada na pytanie.
Quentin

2

Na podstawie ( dangerousouslySetInnerHTML ).

To rekwizyt, który robi dokładnie to, czego chcesz. Jednak nazywają to, aby przekazać, że należy go używać z ostrożnością


1
cóż, według dokumentów wydaje się, że to jedyny powód, wciąż zdezorientowany
mkb
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.