React.js: Tetapkan innerHTML vs berbahayaSetInnerHTML


171

Apakah ada perbedaan "di balik layar" dari pengaturan innerHTML elemen vs pengaturan properti hazardSetInnerHTML pada elemen? Anggaplah saya membersihkan barang dengan benar demi kesederhanaan.

Contoh:

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

Saya melakukan sesuatu yang sedikit lebih rumit daripada contoh di atas, tetapi gagasan keseluruhannya sama

Jawaban:


237

Ya ada perbedaan!

Efek langsung menggunakan innerHTMLversus dangerouslySetInnerHTMLidentik - simpul DOM akan memperbarui dengan HTML yang disuntikkan.

Namun , di balik layar ketika Anda menggunakannya dangerouslySetInnerHTMLmemungkinkan Bereaksi mengetahui bahwa HTML di dalam komponen itu bukanlah sesuatu yang ia pedulikan.

Karena Bereaksi menggunakan DOM virtual, ketika ia pergi untuk membandingkan diff terhadap DOM yang sebenarnya, ia dapat langsung memotong memotong memeriksa anak-anak dari simpul itu karena tahu HTML berasal dari sumber lain . Jadi ada keuntungan kinerja.

Lebih penting lagi , jika Anda hanya menggunakan innerHTML, Bereaksi tidak memiliki cara untuk mengetahui simpul DOM telah dimodifikasi. Lain kali renderfungsi dipanggil, Bereaksi akan menimpa konten yang secara manual disuntikkan dengan apa yang menurutnya keadaan yang benar dari simpul DOM seharusnya.

Solusi Anda untuk digunakan componentDidUpdateuntuk selalu memastikan konten sinkron. Saya yakin ini akan berhasil, tetapi mungkin ada flash selama setiap render.


11
Saya menulis sebuah tes perfiln kecil non-ilmiah untuk menunjukkan perbedaan antara inlining SVG dan menggunakan dangerouslySetInnerHTML: webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - menyelaraskan metode innerHTML hampir dua kali lebih cepat (lihat konsol di webpackbin)
Joscha

4
Itu benar dan mudah diprediksi. Karena innerHTML adalah metode asli yang mengikat kode SVG langsung ke DOM tanpa mempertimbangkan apa pun. Di sisi lain, hazardSetInnerHTML adalah metode yang berasal dari Bereaksi bahwa kode SVG harus diuraikan sebagai komponen Bereaksi anak-anak sebelum menempatkan mereka ke DOM virtual dan kemudian membuat ke DOM.
Up209d

3

Menurut Dangerously Set innerHTML ,

Penggunaan yang tidak benar innerHTMLdapat membuka Anda terhadap serangan skrip lintas situs (XSS) . Membersihkan input pengguna untuk tampilan sangat rentan kesalahan, dan kegagalan untuk membersihkan dengan benar adalah salah satu penyebab utama kerentanan web di internet.

Filosofi desain kami adalah bahwa hal itu "mudah" untuk membuat segalanya aman, dan pengembang harus secara eksplisit menyatakan niat mereka ketika melakukan operasi "tidak aman". Nama prop dangerouslySetInnerHTMLsecara sengaja dipilih untuk menjadi menakutkan, dan nilai prop (objek bukan string) dapat digunakan untuk menunjukkan data yang disanitasi.

Setelah sepenuhnya memahami konsekuensi keamanan __htmldan membersihkan data dengan benar, buat objek baru yang hanya berisi kunci dan data sanitasi Anda sebagai nilainya. Berikut ini adalah contoh menggunakan sintaks JSX:

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

<div dangerouslySetInnerHTML={createMarkup()} /> 

Baca lebih lanjut tentang itu menggunakan tautan di bawah ini:

dokumentasi : Bereaksi DOM Elements - berbahayaSetInnerHTML .


1
Ini tidak menjawab pertanyaan.
Quentin

2

Berdasarkan ( berbahayaSetInnerHTML ).

Ini adalah alat peraga yang melakukan apa yang Anda inginkan. Namun mereka menamainya untuk menyampaikan bahwa itu harus digunakan dengan hati-hati


1
baik menurut dokumen tampaknya ini adalah satu-satunya alasan, masih bingung
mkb
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.