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

Jshoe523
źródło

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.

Francis John
źródło
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 .

Ganesh Sanap
źródło
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ą

Jason
źródło
1
cóż, według dokumentów wydaje się, że to jedyny powód, wciąż zdezorientowany
mkb