Javascript 如何将onclick事件添加到reactjs中由危险的lySetinerHTML呈现的字符串中?
我有一根绳子,也就是Javascript 如何将onclick事件添加到reactjs中由危险的lySetinerHTML呈现的字符串中?,javascript,html,reactjs,onclick,innerhtml,Javascript,Html,Reactjs,Onclick,Innerhtml,我有一根绳子,也就是 let string= "Hello <b>Click here</b>"; render() { return (<div dangerouslySetInnerHTML={this.createMarkup(value)}/> } createMarkup = value => { return { __html: value }; }; let string=“Hello单击此处”; render()
let string= "Hello <b>Click here</b>";
render() {
return (<div dangerouslySetInnerHTML={this.createMarkup(value)}/>
}
createMarkup = value => {
return { __html: value };
};
let string=“Hello单击此处”;
render(){
返回(
}
createMarkup=value=>{
返回{uuuhtml:value};
};
我想要的是能够将onclick事件添加到
标记,并在单击时执行状态操作
根本的问题是,我有一个函数,它应该呈现API传递的任何内容。API将发送一个字符串“Money received for order ID 123”,或者可以是我无法控制的任何字符串。后来,我得到一个要求,即粗体的项必须是可单击的,以便执行一些操作。我没有没有其他解决办法
如何实现这一点?警告:这听起来像是一个问题,根本问题(不管是什么)应该以不同的方式解决,这样您就不必向通过危险的LysetinerHTML创建的DOM元素添加单击处理程序(理想情况下,您根本不必通过危险的SetinenerHTML
创建DOM元素)。但是回答您提出的问题:(您已经澄清了用例;下面的解决方案1适用,并且不是不好的做法。)
我认为你不能直接这么做。我可以想到两种解决方案:
在div
上使用委托事件处理程序:在div
上添加一个click处理程序,但仅当click通过b
元素时才采取操作
在div
上使用ref
,然后在componentDidMount
和componentdiddupdate
中连接单击处理程序(通过querySelector
或类似工具查找div
中的b
元素),大致如下:
下面是#1的一个例子:
…或者,如果您需要支持没有ParentNode#closest
的旧浏览器:
clickHandler(e) {
// `target` is the element the click was on (the div we hooked or an element
// with in it), `currentTarget` is the div we hooked the event on
let el = e.target;
while (el && el !== e.currentTarget && el.tagName !== "B") {
el = el.parentNode;
}
if (el && el.tagName === "B") {
// ...do your state change...
}
}
…以及在构造函数中绑定clickHandler
的位置(而不是使用带有箭头函数的属性;原因:,):
实例:
let string=“Hello单击此处”;
类示例扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
点击次数:0
};
this.clickHandler=this.clickHandler.bind(this);
}
clickHandler(e){
//'target'是单击的元素(我们钩住的div或元素)
//其中,`currentTarget`是我们挂接事件的div
//支持旧浏览器的版本:
设el=e.target;
而(el&&el!==e.currentTarget&&el.tagName!==B){
el=el.parentNode;
}
如果(el&&el.tagName==“B”){
this.setState(({clicks})=>({clicks:clicks+1}));
}
//现代浏览器的替代方案:
/*
常数el=e.目标最近(“B”);
if(el&&e.currentTarget.contains(el)){
this.setState(({clicks})=>({clicks:clicks+1}));
}
*/
}
createMarkup=value=>{
返回{uuuhtml:value};
};
render(){
const{clicks}=this.state;
返回[
点击:{Clicks},
];
}
}
ReactDOM.render(
,
document.getElementById(“根”)
);
这里有一个简单的方法来满足您的需要。通过根据
标记拆分字符串,您可以得到一个可映射的文本数组:
类BoldText扩展React.Component{
建造师(道具){
超级(道具)
此.state={
输入:“订单ID 123收到的钱,哇,真的,太酷了,太疯狂了”
}
}
boldClick=ev=>{
console.log('clicked!')
}
render(){
const{input}=this.state
常量a=输入。拆分(“”)
常量过滤器=/*/
const text=input.split(过滤器)
const clickable=filter.exec(输入)
//
返回(
{a.map(t=>{
常量[文本,粗体]=t.split(“”)
返回{text}{bold}
})}
)
}
}
ReactDOM.render(,document.getElementById('root'))
可以将HTML字符串转换为React组件
使用transform回调函数,您可以使用JSX标记更新HTML字符串中的任何标记,并添加任何属性和事件侦听器
我就是这样使用它的:
ReactHtmlParser(item.value, {
transform: (node) => {
if (node.name === 'a' && node.attribs && node.attribs.href) {
const matched = node.attribs.href.match(/^activity\/([0-9]+)$/i);
if (matched && matched[1]) { // activity id
return <a
href={node.attribs.href}
onClick={(e) => {
e.preventDefault();
this.props.openActivityModal(matched[1]);
}}
>{node.children[0].data}</a>
}
}
}
})
reactHTMLPasser(item.value{
变换:(节点)=>{
if(node.name=='a'&&node.attribs&&node.attribs.href){
const matched=node.attribs.href.match(/^activity\/([0-9]+)$/i);
if(matched&&matched[1]){//活动id
返回
}
}
}
})
为什么要这样做?用例是什么?它看起来像一个;如果可能的话,最好以不同的方式解决根本问题。是否应value
在this.createMarkup(value)中
bestring
?你不能这么做。通过危险的设置HTML,你将离开React作用域,你将无法调用它,即使你让它工作起来,也会很难看,可能有风险。如果你想让React处理某件事,请使用React。如果你想让你的
标记更新状态,然后使用React正确创建它。在React中,返回的元素应该至少有一个父元素。我将拆分“string”分为两个字符串,元素应该作为react元素而不是字符串。虽然这种情况确实应该用另一种方法解决,但我认为使用refs
对react初学者来说不是一个很好的建议,因为它被认为是一个不好的方法practice@Treycos-裁判对于他们所做的事情来说并不是不好的练习。但是正如我在评论t他问了这个问题,以及答案的开头(现在是结尾),不管潜在的问题是什么,它几乎肯定应该以不同的方式来解决。@Treycos-过了一个愉快的时刻,添加了一个更好的解决方案。:-)哦,哇,这是很多代码。Whi
clickHandler(e) {
// `target` is the element the click was on (the div we hooked or an element
// with in it), `currentTarget` is the div we hooked the event on
let el = e.target;
while (el && el !== e.currentTarget && el.tagName !== "B") {
el = el.parentNode;
}
if (el && el.tagName === "B") {
// ...do your state change...
}
}
this.clickHandler = this.clickHandler.bind(this);
ReactHtmlParser(item.value, {
transform: (node) => {
if (node.name === 'a' && node.attribs && node.attribs.href) {
const matched = node.attribs.href.match(/^activity\/([0-9]+)$/i);
if (matched && matched[1]) { // activity id
return <a
href={node.attribs.href}
onClick={(e) => {
e.preventDefault();
this.props.openActivityModal(matched[1]);
}}
>{node.children[0].data}</a>
}
}
}
})