React - как передать HTML теги в реквизит?
Я хочу иметь возможность передавать текст с тегами HTML, например:
<MyComponent text="This is <strong>not</strong> working." />
но внутри MyComponent метод рендеринга, когда я распечатываю this.props.text, он буквально печатает все:
This is <strong>not</strong> working.
есть ли какой-то способ заставить реагировать парсить HTML и выбросить все это правильно?
14 ответов:
вы можете использовать смешанные массивы со строками и элементами JSX (см. docs здесь):
<MyComponent text={["This is ", <strong>not</strong>, "working."]} />здесь есть скрипка, которая показывает, что она работает:http://jsfiddle.net/7s7dee6L/
также, в крайнем случае, у вас всегда есть возможность вставки raw HTML но будьте осторожны, потому что это может открыть вас для атаки межсайтового скриптинга (XSS), если вы не очищаете значения свойств.
на самом деле, есть несколько способов, чтобы пойти с этим.
вы хотите использовать JSX внутри вашего реквизита
вы можете просто использовать {}, чтобы заставить JSX анализировать параметр. Единственное ограничение такое же, как и для каждого элемента JSX: он должен возвращать только один корневой элемент.
myProp={<div><SomeComponent>Some String</div>}лучший читаемый способ сделать это-создать функцию renderMyProp, которая будет возвращать компоненты JSX (так же, как стандартная функция рендеринга), а затем просто вызвать myProp={ этот.renderMyProp ()}
вы хотите передать только HTML в виде строки
по умолчанию JSX не позволяет отображать необработанный HTML из строковых значений. Однако есть способ заставить его сделать это:
myProp="<div>This is some html</div>"тогда в вашем компоненте вы можете использовать его так:
<div dangerouslySetInnerHTML=myProp={{ __html: this.renderMyProp() }}></div>будьте осторожны,что это решение "может" открыть на межсайтовых скриптовых подделок атак. Также помните, что вы можете отображать только простой HTML, без тега JSX или компонента или другой фантазии вещи.
путь массива
в react можно передать массив элементов JSX. Это значит:
myProp={["This is html", <span>Some other</span>, "and again some other"]}Я бы не рекомендовал этот метод, потому что:
- он создаст предупреждение (отсутствующие ключи)
- это не читается
- это не совсем способ JSX, это больше Хак, чем предполагаемый дизайн.
дети так
добавляя его для полноты, но в react, вы также можно получить все дети, которые находятся "внутри" вашего компонента.
так что если я возьму следующий код:
<SomeComponent> <div>Some content</div> <div>Some content</div> </SomeComponent>тогда два дива будут доступны как это.реквизит.дочерние элементы в SomeComponent и могут быть отображены со стандартным синтаксисом {}.
это решение идеально подходит, когда у вас есть только один HTML-контент для передачи в ваш компонент (представьте себе компонент Popin, который принимает только содержимое Popin в качестве детей).
однако, если у вас есть несколько содержание, вы не можете использовать детей (или вам нужно хотя бы объединить его с другим решением здесь)
можно использовать dangerouslySetInnerHTML
просто отправьте html в виде обычной строки
<MyComponent text="This is <strong>not</strong> working." />и визуализировать в коде JSX следующим образом:
<h2 className="header-title-right wow fadeInRight" dangerouslySetInnerHTML={{__html: props.text}} />просто будьте осторожны, если вы оказываете данные, введенные пользователем. Вы можете стать жертвой атаки XSS
вот документация: https://facebook.github.io/react/tips/dangerously-set-inner-html.html
для меня это работало, передавая HTML-тег в реквизит детей
<MyComponent>This is <strong>not</strong> working.</MyComponent> var MyComponent = React.createClass({ render: function() { return ( <div>this.props.children</div> ); },
<MyComponent text={<span>This is <strong>not</strong> working.</span>} />и тогда в вашем компоненте вы можете сделать проверку prop следующим образом:
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 } } }убедитесь, что вы выбрали только один тип опоры.
в приложении react на стороне клиента есть несколько способов визуализации prop в виде строки с некоторым html. Один безопаснее другого...
1-Определите опору как jsx (мои предпочтения)
const someProps = { greeting: {<div>Hello<a href="/${name_profile}">${name_profile}</a></div>} } const GreetingComopnent = props => ( <p>{props.someProps.greeting}</p> )• единственное требование здесь заключается в том, что любой файл, генерирующий эту опору, должен включать React как зависимость (в случае, если вы генерируете JSX опоры в вспомогательном файле и т. д.).
2-опасно установить innerHtml
const someProps = { greeting: '<React.Fragment>Hello<a href="/${name_profile}">${name_profile}</a></React.Fragment>' } const GreetingComponent = props => { const innerHtml = { __html: props.someProps.greeting } return <p dangerouslySetInnerHtml={innerHtml}></p> }• Этот второй подход не поощряется. Представьте себе поле ввода, входное значение которого отображается как опора в этом компоненте. Пользователь может ввести тег сценария во входные данные, и компонент, который отображает эти входные данные, выполнит этот потенциально вредоносный код. Таким образом, этот подход может привести к появлению уязвимостей межсайтовых сценариев. Для получения дополнительной информации обратитесь к официальным документам React
вы можете сделать это двумя способами, о которых я знаю.
1-
<MyComponent text={<p>This is <strong>not</strong> working.</p>} />и после этого
class MyComponent extends React.Component { render () { return (<div>{this.props.text}</div>) } }или второй подход сделать это так
2-
<MyComponent><p>This is <strong>not</strong> working.</p><MyComponent/>и после этого
class MyComponent extends React.Component { render () { return (<div>{this.props.children}</div>) } }
из React v16. 02 Вы можете использовать фрагмент.
<MyComponent text={<Fragment>This is an <strong>HTML</strong> string.</Fragment>} />дополнительная информация:https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html
вы также можете использовать функцию на компоненте, чтобы передать JSX через props. например:
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> ); }, });
в моем проекте мне пришлось передать динамический HTML-фрагмент из переменной и отобразить его внутри компонента. Поэтому я сделал следующее.
defaultSelection : { innerHtml: {__html: '<strong>some text</strong>'} }defaultSelection объект передается компоненту из
.jsfile<HtmlSnippet innerHtml={defaultSelection.innerHtml} />HtmlSnippet компонент
var HtmlSnippet = React.createClass({ render: function() { return ( <span dangerouslySetInnerHTML={this.props.innerHtml}></span> ); } });
Да, вы можете это сделать, используя Mix array со строками и элементами JSX. ссылка
<MyComponent text={["This is ", <strong>not</strong>, "working."]} />
есть ли причина, по которой никто не предложил react-html-parser? Похоже, это хороший способ работать с импортированным HTML без необходимости делать это опасно
@matagus ответ Отлично подходит для меня, надеюсь, что ниже фрагмент поможет тем, кто хочет использовать переменную внутри.
const myVar = 'not'; <MyComponent text={["This is ", <strong>{`${myVar}`}</strong>, "working."]} />
добавили html в componentDidMount с помощью jQuery append. Это должно решить проблему.
var MyComponent = React.createClass({ render: function() { return ( <div> </div> ); }, componentDidMount() { $(ReactDOM.findDOMNode(this)).append(this.props.text); } });
Comments