Javascript 如何将JSX组件与危险的HTML结合起来
我正在显示存储在数据库中的文本。数据以字符串形式来自firebase(包括换行符)。为了使其显示为HTML,我最初执行了以下操作:Javascript 如何将JSX组件与危险的HTML结合起来,javascript,reactjs,react-router,react-router-component,Javascript,Reactjs,React Router,React Router Component,我正在显示存储在数据库中的文本。数据以字符串形式来自firebase(包括换行符)。为了使其显示为HTML,我最初执行了以下操作: <p className="term-definition" dangerouslySetInnerHTML={{__html: (definition.definition) ? definition.definition.replace(/(?:\r\n|\r|\n)/g, '<br />') : ''}}></p&
<p className="term-definition"
dangerouslySetInnerHTML={{__html: (definition.definition) ? definition.definition.replace(/(?:\r\n|\r|\n)/g, '<br />') : ''}}></p>
我省略了this.permalink
方法,因为它不相关。如您所见,我试图返回从react-router导入的
组件。但是,由于它是原始HTML,危险的HTML
不再正常工作
所以我有点被困在这一点上。如何设置内部文本的格式并创建链接?您可以将文本拆分为链接+字符串数组,如下所示:
import {Link} from 'react-router';
const paragraphWithLinks = ({markdown}) => {
const linkRegex = /\[([\w\s-']+)\]/g;
const children = _.chain(
markdown.split(linkRegex) // get the text between links
).zip(
markdown.match(linkRegex).map( // get the links
word => <Link to={`/terms/${permalink(word)}/1`}>{word}</Link> // and convert them
)
).flatten().thru( // merge them
v => v.slice(0, -1) // remove the last element (undefined b/c arrays are different sizes)
).value();
return <p className='term-definition'>{children}</p>;
};
从'react router'导入{Link};
常量段落WithLinks=({markdown})=>{
常量linkRegex=/\[([\w\s-']+)\]/g;
const children=uz.chain(
markdown.split(linkRegex)//获取链接之间的文本
)zip先生(
markdown.match(linkRegex).map(//获取链接
word=>{word}//并将其转换为
)
).flant().thru(//合并它们
v=>v.slice(0,-1)//删除最后一个元素(未定义的b/c数组大小不同)
).value();
返回{children}
;
};
这种方法最好的地方就是不再需要使用危险的HTML
。使用它通常是一个非常糟糕的想法,因为您可能会创建XSS漏洞。例如,这可能会使黑客窃取用户的登录凭据
在大多数情况下,您不需要使用
危险的ethtml
。明显的例外是与第三方库的集成,这仍然需要仔细考虑。我遇到了类似的情况,但是接受的解决方案对我来说不是一个可行的选择
我使用react-dom
以一种相当粗糙的方式实现了这一点。我将组件设置为侦听单击事件,如果单击具有react router link
类。发生这种情况时,如果项目具有数据url
属性集,则它将使用浏览器历史记录。推送
。我目前正在使用一个同构的应用程序,这些点击事件对于服务器的生成没有意义,所以我只是有条件地设置这些事件
以下是我使用的代码:
import React from 'react';
import _ from 'lodash';
import { browserHistory } from 'react-router'
export default class PostBody extends React.Component {
componentDidMount() {
if(! global.__SERVER__) {
this.listener = this.handleClick.bind(this);
window.addEventListener('click', this.listener);
}
}
componentDidUnmount() {
if(! global.__SERVER__) {
window.removeEventListener("scroll", this.listener);
}
}
handleClick(e) {
if(_.includes(e.target.classList, "react-router-link")) {
window.removeEventListener("click", this.listener);
browserHistory.push(e.target.getAttribute("data-url"));
}
}
render() {
function createMarkup(html) { return {__html: html}; };
return (
<div className="col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3 col-lg-8 col-lg-offset-2 post-body">
<div dangerouslySetInnerHTML={createMarkup(this.props.postBody)} />
</div>
);
}
}
从“React”导入React;
从“lodash”进口;
从“react router”导入{browserHistory}
导出默认类PostBody扩展React.Component{
componentDidMount(){
如果(!全局.\uuuu服务器\uuu){
this.listener=this.handleClick.bind(this);
window.addEventListener('click',this.listener);
}
}
componentDidUnmount(){
如果(!全局.\uuuu服务器\uuu){
removeEventListener(“滚动”,this.listener);
}
}
handleClick(e){
如果(u.includes(例如target.classList,“反应路由器链接”)){
window.removeEventListener(“单击”,this.listener);
browserHistory.push(例如target.getAttribute(“数据url”);
}
}
render(){
函数createMarkup(html){return{{uuuuhtml:html};};
返回(
);
}
}
希望这有帮助 什么是链子?你在用下划线吗?我没有把它作为这个项目的一部分,也不想添加其他依赖项。它来自
lodash
。非常类似于下划线,非常棒。我已经向您介绍了如何创建标记解析器的要点—具体实现取决于您。.chain
允许您按顺序执行函数,将输入从一个函数传递到下一个函数。
import React from 'react';
import _ from 'lodash';
import { browserHistory } from 'react-router'
export default class PostBody extends React.Component {
componentDidMount() {
if(! global.__SERVER__) {
this.listener = this.handleClick.bind(this);
window.addEventListener('click', this.listener);
}
}
componentDidUnmount() {
if(! global.__SERVER__) {
window.removeEventListener("scroll", this.listener);
}
}
handleClick(e) {
if(_.includes(e.target.classList, "react-router-link")) {
window.removeEventListener("click", this.listener);
browserHistory.push(e.target.getAttribute("data-url"));
}
}
render() {
function createMarkup(html) { return {__html: html}; };
return (
<div className="col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3 col-lg-8 col-lg-offset-2 post-body">
<div dangerouslySetInnerHTML={createMarkup(this.props.postBody)} />
</div>
);
}
}