React.js: Đặt InternalHTML so với nguy hiểm SetInnerHTML


171

Có sự khác biệt "đằng sau hậu trường" nào so với việc đặt bên trongHTML của phần tử so với đặt thuộc tính nguy hiểm SetInnerHTML trên một phần tử không? Giả sử tôi vệ sinh mọi thứ đúng cách vì đơn giản.

Thí dụ:

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

đấu với

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

Tôi đang làm một cái gì đó phức tạp hơn một chút so với ví dụ trên, nhưng ý tưởng tổng thể là như nhau

Câu trả lời:


236

Có một sự khác biệt!

Hiệu quả ngay lập tức của việc sử dụng innerHTMLso với dangerouslySetInnerHTMLlà giống hệt nhau - nút DOM sẽ cập nhật với HTML được chèn.

Tuy nhiên , đằng sau hậu trường khi bạn sử dụng dangerouslySetInnerHTMLnó cho React biết rằng HTML bên trong thành phần đó không phải là thứ mà nó quan tâm.

Vì React sử dụng DOM ảo, nên khi so sánh diff với DOM thực tế, nó có thể bỏ qua việc kiểm tra các phần tử con của nút đó bởi vì nó biết HTML đến từ một nguồn khác . Vì vậy, có hiệu suất tăng.

Quan trọng hơn , nếu bạn chỉ đơn giản sử dụng innerHTML, React không có cách nào để biết nút DOM đã được sửa đổi. Lần sau khi renderhàm được gọi, React sẽ ghi đè lên nội dung được chèn thủ công với nội dung mà nó nghĩ là trạng thái chính xác của nút DOM đó.

Giải pháp của bạn để sử dụng componentDidUpdateđể luôn đảm bảo nội dung được đồng bộ hóa Tôi tin rằng sẽ hoạt động nhưng có thể có đèn flash trong mỗi lần kết xuất.


11
Tôi đã viết một bài kiểm tra về hiệu suất nhỏ, không khoa học để thấy sự khác biệt giữa nội tuyến tập tin SVG lên và sử dụng dangerouslySetInnerHTML: webpackbin.com/bins/-KepHa-AMxQgGxOUnAac - tuns ra phương pháp innerHTML là gần như nhanh gấp hai lần (xem giao diện điều khiển trong webpackbin)
Joscha

4
Đó là sự thật và dễ dự đoán. Vì InternalHTML là một phương thức riêng liên kết trực tiếp mã SVG với DOM mà không xem xét bất cứ điều gì. Mặt khác, nguy hiểm là SetInnerHTML là phương thức xuất phát từ React rằng mã SVG phải được phân tích cú pháp dưới dạng các phần tử React trước khi đưa chúng vào DOM ảo và sau đó kết xuất với DOM.
Up209d

3

Theo Nguy hiểm thiết lập bên trongHTML ,

Việc sử dụng không đúng cách innerHTMLcó thể mở ra cho bạn một cuộc tấn công kịch bản chéo trang (XSS) . Vệ sinh đầu vào của người dùng để hiển thị rất dễ bị lỗi và việc không vệ sinh đúng cách là một trong những nguyên nhân hàng đầu gây ra lỗ hổng web trên internet.

Triết lý thiết kế của chúng tôi là nó phải "dễ dàng" để làm cho mọi thứ an toàn và các nhà phát triển nên nói rõ ý định của họ khi thực hiện các hoạt động không an toàn của Wap. Tên prop dangerouslySetInnerHTMLđược cố ý chọn là đáng sợ và giá trị prop (một đối tượng thay vì chuỗi) có thể được sử dụng để chỉ ra dữ liệu được khử trùng.

Sau khi hiểu đầy đủ các phân nhánh bảo mật và vệ sinh dữ liệu đúng cách, hãy tạo một đối tượng mới chỉ chứa khóa __htmlvà dữ liệu được khử trùng của bạn làm giá trị. Dưới đây là một ví dụ sử dụng cú pháp JSX:

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

<div dangerouslySetInnerHTML={createMarkup()} /> 

Đọc thêm về nó bằng cách sử dụng liên kết dưới đây:

tài liệu : Phản ứng các thành phần DOM - nguy hiểm SetInnerHTML .


1
Điều này không trả lời câu hỏi.
Quentin

2

Dựa trên ( nguy hiểmInInHTMLHTML ).

Đó là một chỗ dựa làm chính xác những gì bạn muốn. Tuy nhiên, họ đặt tên cho nó để truyền đạt rằng nó nên được sử dụng một cách thận trọng


1
theo tài liệu thì có vẻ như đây là lý do duy nhất, vẫn còn bị nhầm lẫn
mkb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.