React - Làm thế nào để chuyển các thẻ HTML trong các đạo cụ?


118

Tôi muốn có thể chuyển văn bản bằng các thẻ HTML, như sau:

<MyComponent text="This is <strong>not</strong> working." />

Nhưng bên trong MyComponentphương thức kết xuất của, khi tôi in ra this.props.text, nó thực sự in ra mọi thứ:

This is <strong>not</strong> working.

Có cách nào để làm cho React phân tích cú pháp HTML và kết xuất nó đúng cách không?


Chức năng kết xuất thực tế của bạn là gì?
Lucio

3
Mô hình điển hình sẽ là làm cho nội dung của bạn là con của thành phần của bạn <MyComponent>This is <strong>not</strong> working</MyComponent>, thay vì chuyển chúng làm đạo cụ. Bạn có thể cung cấp thêm bối cảnh về những gì bạn thực sự đang cố gắng hoàn thành không?
Nick Tomlin

Câu hỏi gần giống như vậy: Reactjs chuyển đổi thành html .
totymedli

Câu trả lời:


140

Bạn có thể sử dụng mảng hỗn hợp với các chuỗi và phần tử JSX (xem tài liệu tại đây ):

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />

Có một fiddle ở đây cho thấy nó đang hoạt động: http://jsfiddle.net/7s7dee6L/

Ngoài ra, phương sách cuối cùng, bạn luôn có khả năng chèn HTML thô nhưng hãy cẩn thận vì điều đó có thể mở ra cho bạn một cuộc tấn công tập lệnh trên nhiều trang web (XSS) nếu không làm sạch các giá trị thuộc tính.


10
Điều này hoạt động, ngoại trừ bây giờ tôi nhận được cảnh báo: Cảnh báo: Mỗi phần tử con trong một mảng hoặc trình vòng lặp phải có một chỗ dựa "khóa" duy nhất. Kiểm tra phương thức hiển thị của CTA. Nó đã được thông qua một đứa trẻ từ Template1. Xem fb.me/react-warning-keys để biết thêm thông tin.
ffxsam

3
Bạn có thể làm cho lỗi này biến mất bằng cách đi qua mảng và thêm chỉ mục làm khóa trong MyComponent {text.map( textOrHTML, index) => <span key={index}>{textOrHTML}</span> )} Mặc dù, thật kỳ lạ khi chúng ta phải thực hiện điều này ngay từ đầu.
HussienK

5
Bạn cũng có thể sửa cảnh báo bằng cách đưa key="[some unique value]"vào <strong>phần tử.
Chad Johnson

Nice, làm việc tốt, tôi muốn biết làm thế nào tôi có thể sử dụng một biến bên trong mạnh mẽ thay vì chuỗi 'không'
Jaison

2
Để loại bỏ cảnh báo khóa mảng, bây giờ cũng có thể chuyển một JSX như thế này. <MyComponent text={<>This is <strong>not</strong> working.</>} />
Arif

111

Trên thực tế, có nhiều cách để làm điều đó.

Bạn muốn sử dụng JSX bên trong đạo cụ của mình

Bạn có thể chỉ cần sử dụng {} để khiến JSX phân tích cú pháp tham số. Hạn chế duy nhất giống với mọi phần tử JSX: Nó chỉ được trả về một phần tử gốc.

myProp={<div><SomeComponent>Some String</div>}

Cách dễ đọc nhất để thực hiện điều này là tạo một hàm renderMyProp sẽ trả về các thành phần JSX (giống như hàm kết xuất tiêu chuẩn) và sau đó chỉ cần gọi myProp = {this.renderMyProp ()}

Bạn chỉ muốn chuyển HTML dưới dạng một chuỗi

Theo mặc định, JSX không cho phép bạn hiển thị HTML thô từ các giá trị chuỗi. Tuy nhiên, có một cách để thực hiện điều đó:

myProp="<div>This is some html</div>"

Sau đó, trong thành phần của bạn, bạn có thể sử dụng nó như vậy:

<div dangerouslySetInnerHTML=myProp={{ __html: this.renderMyProp() }}></div>

Lưu ý rằng giải pháp này 'có thể' mở trên các cuộc tấn công giả mạo tập lệnh trên nhiều trang web. Cũng nên lưu ý rằng bạn chỉ có thể hiển thị HTML đơn giản, không có thẻ hoặc thành phần JSX hoặc những thứ lạ mắt khác.

Cách mảng

Trong phản ứng, bạn có thể chuyển một mảng các phần tử JSX. Điều đó có nghĩa là:

myProp={["This is html", <span>Some other</span>, "and again some other"]}

Tôi sẽ không đề xuất phương pháp này vì:

  • Nó sẽ tạo ra một cảnh báo (thiếu khóa)
  • Nó không thể đọc được
  • Đó không thực sự là cách JSX, nó giống như một sự tấn công hơn là một thiết kế dự kiến.

Con đường

Thêm nó vì mục đích hoàn chỉnh nhưng trong phản ứng, bạn cũng có thể nhận được tất cả các phần tử con nằm 'bên trong' thành phần của bạn.

Vì vậy, nếu tôi lấy mã sau:

<SomeComponent>
    <div>Some content</div>
    <div>Some content</div>
</SomeComponent>

Sau đó, hai div sẽ có sẵn dưới dạng this.props.children trong SomeComponent và có thể được hiển thị với cú pháp {} chuẩn.

Giải pháp này hoàn hảo khi bạn chỉ có một nội dung HTML để chuyển cho Thành phần của mình (Hãy tưởng tượng một thành phần Popin chỉ nhận nội dung của Popin khi còn nhỏ).

Tuy nhiên, nếu bạn có nhiều nội dung, bạn không thể sử dụng con (hoặc ít nhất bạn cần kết hợp nó với một giải pháp khác ở đây)


1
this.props.childrens - nhưng this.props.children. Không có 's' reactjs.org/docs/glossary.html#propschildren
Alexiuscrow

13

Bạn có thể sử dụng một cách nguy hiểmSetInnerHTML

Chỉ cần gửi html dưới dạng một chuỗi bình thường

<MyComponent text="This is <strong>not</strong> working." />

Và hiển thị trong mã JSX như sau:

<h2 className="header-title-right wow fadeInRight"
    dangerouslySetInnerHTML={{__html: props.text}} />

Chỉ cần cẩn thận nếu bạn đang hiển thị dữ liệu do người dùng nhập. Bạn có thể là nạn nhân của một cuộc tấn công XSS

Đây là tài liệu: https://facebook.github.io/react/tips/dangerously-set-inner-html.html


7
<MyComponent text={<span>This is <strong>not</strong> working.</span>} />

và sau đó trong thành phần của bạn, bạn có thể thực hiện kiểm tra chống đỡ như vậy:

import React from 'react';
export default class MyComponent extends React.Component {
  static get propTypes() {
    return {
      text: React.PropTypes.object, // if you always want react components
      text: React.PropTypes.any, // if you want both text or react components
    }
  }
}

Đảm bảo rằng bạn chỉ chọn một loại chân chống.


6

Đối với tôi, nó hoạt động bằng cách chuyển thẻ html trong props con

<MyComponent>This is <strong>not</strong> working.</MyComponent>


var MyComponent = React.createClass({

   render: function() {
    return (
      <div>this.props.children</div>
    );
   },


6

Trên ứng dụng phản ứng phía máy khách, có một số cách để hiển thị một phần mềm hỗ trợ dưới dạng một chuỗi với một số html. Một cái an toàn hơn cái kia ...

1 - Định nghĩa prop là jsx (tùy chọn của tôi)

const someProps = {
  greeting: {<div>Hello<a href="/${name_profile}">${name_profile}</a></div>}
}


const GreetingComopnent = props => (
  <p>{props.someProps.greeting}</p>
)

• Yêu cầu duy nhất ở đây là bất kỳ tệp nào đang tạo ra phần mềm hỗ trợ này cần phải bao gồm React làm phụ thuộc (trong trường hợp bạn đang tạo jsx của phần mềm hỗ trợ trong tệp trợ giúp, v.v.).

2 - Đặt innerHtml một cách nguy hiểm

const someProps = {
  greeting: '<React.Fragment>Hello<a href="https://stackoverflow.com/${name_profile}">${name_profile}</a></React.Fragment>'
}

const GreetingComponent = props => {
  const innerHtml = { __html: props.someProps.greeting }
  return <p dangerouslySetInnerHtml={innerHtml}></p>
}

• Cách tiếp cận thứ hai này không được khuyến khích. Hãy tưởng tượng một trường đầu vào có giá trị đầu vào được hiển thị như một chỗ dựa trong thành phần này. Người dùng có thể nhập thẻ tập lệnh vào đầu vào và thành phần hiển thị đầu vào này sẽ thực thi mã độc hại tiềm ẩn này. Do đó, cách tiếp cận này có khả năng tạo ra các lỗ hổng tập lệnh trên nhiều trang web. Để biết thêm thông tin, hãy tham khảo tài liệu React chính thức


4

Đặt kiểu chống đỡ văn bản thành bất kỳ và thực hiện điều này:

<MyComponent text={
    <React.Fragment>
        <div> Hello, World!</div>
    </React.Fragment>
    } 
/>

Thí dụ


3

Bạn có thể làm điều đó theo 2 cách mà tôi biết.

1- <MyComponent text={<p>This is <strong>not</strong> working.</p>} />

Và sau đó làm điều này

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.text}</div>)
   }
}

Hoặc cách tiếp cận thứ hai làm như thế này

2- <MyComponent><p>This is <strong>not</strong> working.</p><MyComponent/>

Và sau đó làm điều này

class MyComponent extends React.Component {
   render () {
     return (<div>{this.props.children}</div>)
   }
}

1
Tôi đã thêm một biến let vhtml = "<p>Test</p>"và sử dụng nó trên phần mềm như thế này text={vhtml}và nó vẫn hiển thị ở dạng văn bản thuần túy vì một số lý do.
Si8

2

Câu trả lời @matagus là ổn đối với tôi, Hy vọng đoạn mã dưới đây sẽ giúp ích cho những ai muốn sử dụng một biến bên trong.

const myVar = 'not';
<MyComponent text={["This is ", <strong>{`${myVar}`}</strong>,  "working."]} />

1

Trong dự án của mình, tôi phải chuyển đoạn mã html động từ biến và hiển thị nó bên trong thành phần. Vì vậy, tôi đã làm như sau.

defaultSelection : {
    innerHtml: {__html: '<strong>some text</strong>'}
}

Đối tượng defaultSelection được chuyển đến thành phần từ .jstệp

<HtmlSnippet innerHtml={defaultSelection.innerHtml} />

Thành phần HtmlSnippet

var HtmlSnippet = React.createClass({
  render: function() {
    return (
      <span dangerouslySetInnerHTML={this.props.innerHtml}></span>
    );
  }
});

Ví dụ về Plunkr

phản ứng tài liệu cho nguy hiểmSetInnerHTML


1

Bạn cũng có thể sử dụng một hàm trên thành phần để chuyển cùng jsx tới các đạo cụ. giống:

 var MyComponent = React.createClass({

   render: function() {
    return (
      <OtherComponent
        body={this.body}
      />
    );
   },

   body() {
     return(
       <p>This is <strong>now</strong> working.<p>
     );
   }

});

var OtherComponent = React.createClass({

  propTypes: {
    body: React.PropTypes.func
  },

  render: function() {
     return (
        <section>
          {this.props.body()}
        </section>
     );
  },

});

1

Có, bạn có thể làm điều đó bằng cách sử dụng mảng hỗn hợp với các chuỗi và phần tử JSX. tài liệu tham khảo

<MyComponent text={["This is ", <strong>not</strong>,  "working."]} />

1

Phân tích cú pháp từ html-react-parser là một giải pháp tốt. Bạn chỉ cần

  • cài đặt nó bằng npm hoặc sợi
  • nhập Parser từ 'html-react-parser';
  • gọi nó bằng:

    <MyComponent text=Parser("This is <strong>not</strong> working.") />

    và nó hoạt động tốt.


1

Thêm vào câu trả lời: Nếu bạn định phân tích cú pháp và bạn đã ở trong JSX nhưng có một đối tượng có các thuộc tính lồng nhau, một cách rất hay là sử dụng dấu ngoặc đơn để buộc phân tích cú pháp JSX:

const TestPage = () => (
  <Fragment>
    <MyComponent property={
    {
      html: (
        <p>This is a <a href='#'>test</a> text!</p>
      )
    }}>
    </MyComponent>
  </Fragment>
);

1

Câu hỏi này đã có rất nhiều câu trả lời, nhưng tôi đã làm sai điều gì đó liên quan đến điều này và tôi nghĩ đáng để chia sẻ:

Tôi đã có một cái gì đó như thế này:

export default function Features() {
  return (
    <Section message={<p>This is <strong>working</strong>.</p>} />
  }
}

nhưng massage lâu hơn thế, vì vậy tôi đã thử sử dụng một cái gì đó như thế này:

const message = () => <p>This longer message is <strong>not</strong> working.</p>;

export default function Features() {
  return (
    <Section message={message} />
  }
}

Phải mất một lúc tôi mới nhận ra rằng tôi đã thiếu dấu () trong lệnh gọi hàm.

Không làm việc

<Section message={message} />

Đang làm việc

<Section message={message()} />

có lẽ điều này sẽ giúp bạn, như nó đã làm với tôi!


1

Bạn có thể sử dụng thành công các đoạn React cho tác vụ này. Tùy thuộc vào phiên bản bạn sử dụng Phản ứng, bạn có thể sử dụng cú pháp ngắn gọn: <>hoặc đầy đủ thẻ: <React.Fragment>. Hoạt động đặc biệt tốt nếu bạn không muốn bọc toàn bộ chuỗi trong các thẻ HTML.

<MyComponent text={<>Hello World. <u>Don't be so ruthless</u>.</>} />

0

Chúng ta có thể làm điều tương tự theo cách như vậy.

const Child = () => {
  return (
     write your whole HTML here.
  )
}

bây giờ bạn muốn gửi HTML này bên trong một thành phần khác có tên là Thành phần chính.

Gọi: -

<Parent child={<child/>} >
</Parent> 

Sử dụng Trẻ em: -

 const Parent = (props) => {
   const { child } = props; 
   return (
       {child}
    )
}

công việc này hoàn hảo cho tôi.


-9

Đã thêm html trong componentDidMount bằng cách sử dụng jQuery append. Điều này sẽ giải quyết vấn đề.

 var MyComponent = React.createClass({
    render: function() {

        return (
           <div>

           </div>
        );
    },
    componentDidMount() {
        $(ReactDOM.findDOMNode(this)).append(this.props.text);
    }
});

5
Điều này không được bình chọn vì bạn không nên sử dụng thao tác DOM trực tiếp của jquery kết hợp với thao tác DOM gián tiếp của phản ứng, vì nó có thể dẫn đến sự cố trình duyệt.
Allison
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.