我正在使用这个库:html-to-react
因为我发现可以将HTML“编译”为一个字符串来反应组件。
我们正在做一个基于小部件的系统,它们可能会随着时间而改变(即添加/删除/更新/等),因此我们计划将小部件HTML从数据库发送到前端,这是使用React完成的
我已经使用HTML成功完成了一个简单的小部件,现在我正在尝试使用此小部件来响应点击事件,因此我考虑从HTML中添加onclick=method()
方法或从React添加onClick={method}
。但是我无法获得所需的输出,因为我在浏览器的控制台中收到了这些错误。
Warning: Invalid event handler property `onclick`. React events use the camelCase naming convention, for example `onClick`.
in label
in span
in div
Warning: Invalid event handler property `onclick`. Did you mean `onClick`?
in label
in span
in div
in DireccionComponent (at App.js:51)
in div (at App.js:50)
in GridItem (created by ReactGridLayout)
in div (created by ReactGridLayout)
in ReactGridLayout (at App.js:49)
in App (at index.js:11)
我正在使用的代码如下:
App.js
import React, { Component } from 'react';
import './App.css';
import DireccionComponent from './DireccionComponent.js';
class App extends Component {
render() {
return (
<DireccionComponent />
);
}
}
export default App;
DireccionComponent.js
import React, {Component} from 'react';
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = ''
+ '<div>'
+ '<center><label className="title">Widget</label></center>'
+ '<span className="ui-float-label">'
+ '<label htmlFor="float-input" onClick={this.myFunction}>Hello</label>'
+ '</span>'
+ '</div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement);
class DireccionComponent extends Component {
constructor(props) {
super (props);
this.myFunction = this.myFunction.bind(this);
}
render() {
return (
reactElement
)
}
myFunction() {
console.log('Hola');
alert("Hola");
}
}
export default DireccionComponent;
的package.json
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"html-to-react": "^1.3.3",
"primereact": "^1.5.1",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-dom-server": "0.0.5",
"react-grid-layout": "^0.16.6",
"react-scripts": "1.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
使用上面的库将HTML解析为React Components是否可以获得alert
或类似内容?如果是的话,我怎么能这样做?或者我做错了什么?
它不一定是我正在使用的库,如果还有另一个你曾经使用并做过类似的事情,我愿意接受这个建议(注意,我不是要求一个软件或库,但如何在包含我的HTML或变通方法的String中调用onClick
方法
在尝试了一些东西后,我发现删除了这一行:
var reactHtml = ReactDOMServer.renderToStaticMarkup(reactElement);
删除其中一条消息。该库使用该元素来测试当前HTML和解析的HTML是否相同。我没有为我的情况需要它,但仍然在控制台中留下当前错误:
Warning: Invalid event handler property `onclick`. Did you mean `onClick`?
in label
in span
in div
in DireccionComponent (at App.js:47)
in App (at index.js:11)
经过一些调查后,我在dangerousSetInnerHTML
然后我尝试按照this answer在我的HTML中放置一个alert
,如下所示:
'<label htmlFor="float-input" onclick="alert(\'Hello\')">Hello2</label>'
它触发了alert
,但是如果我在下面的代码中声明myFunction
(注意我试图在课外宣布它为function
,在它内部也是如此var myFunction = function() { ... }
所有在一起并分开):
import React, {Component} from 'react';
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = ''
//+ '<div>'
+ '<center><label className="title">Widget</label></center>'
+ '<span className="ui-float-label">'
+ '<label htmlFor="float-input" onclick="myFunction()">Hello2</label>'
+ '</span>'
//+ '</div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
class DireccionComponent extends Component {
constructor(props) {
super (props);
this.myFunction = this.myFunction.bind(this);
}
render() {
return (
<div dangerouslySetInnerHTML={{__html: htmlInput}}>
</div>
)
}
myFunction() {
console.log('Hola');
alert("Hola");
}
}
function myFunction() {
console.log('Hola');
alert("Hola");
}
export default DireccionComponent;
但这一次我收到了一个新错误:
ReferenceError: myFunction is not defined[Learn More]
我发现了一个类似的问题:Handling onClick of a <a> tag inside of dangerouslySetInnerHTML/regular html出现此问题,并尝试进行更多调查,发现this comment表示来自dangerouslySetInnerHTML
的事件不会被触发方式和指向docs的链接。
所以,虽然当我直接从alert
方法编写onclick
时,这似乎是一种解决方法,或者我可能没有以正确的方式执行,所以如果有人更多经验可以尝试并澄清,会很棒。
我找到了一种以这种方式显示alert
的方法:
dangerouslySetInnerHTML
componentDidMound()
函数使用纯Javascript向其添加onclick
函数。然而,我们要做的是:
addTwoNumbers
或类似的方法onclick
函数的HTML字符串中发送onClick
或addTwoNumbers
。addTwoNumbers
方法的新组件时重复,只需要为它编写HTML,将其保存在数据库中并检索它然后只使用它。类似的东西:
...
<label onClick={myFunction}> My Label </label>
...
或者如上所述:
...
<label onClick={addTwoNumbers}> My Label </label>
...
允许我获得alert
的代码如下:
import React, {Component} from 'react';
import Parser from 'html-react-parser';
import {render} from 'react-dom';
var ReactDOMServer = require('react-dom/server');
var HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = ''
//+ '<div>'
+ '<center><label className="title">Widget</label></center>'
+ '<span className="ui-float-label">'
+ '<label htmlFor="float-input" id="myLabel">Hello2</label>'
+ '</span>'
//+ '</div>';
var htmlToReactParser = new HtmlToReactParser();
var reactElement = htmlToReactParser.parse(htmlInput);
class DireccionComponent extends Component {
constructor(props) {
super (props);
this.myFunction = this.myFunction.bind(this);
}
render() {
return (
<div dangerouslySetInnerHTML={{__html: htmlInput}}>
</div>
)
}
componentDidMount() {
console.log('DONE');
let myLabel = document.getElementById("myLabel");
myLabel.onclick = function() {
alert();
console.log('clicked');
}
console.log(myLabel);
}
myFunction() {
console.log('Hola');
alert("Hola");
}
}
function myFunction() {
console.log('Hola');
alert("Hola");
}
export default DireccionComponent;
考虑到这一点,你知道其他任何方法可以做我想做的事吗?
答案 0 :(得分:3)
解决方案有点hacky,在codesandbox中复制粘贴
"destination folder is the same as the origin"
答案 1 :(得分:0)
我不知道它是否适用于您的特定情况,但一个想法是根本不解析HTML。您可以告诉webpack为不同的文件集生成单独的包。现在,我从来没有这样做过,但我已多次读过你能做到的事了;例如,this。
然后你可以拥有一个main.bundle.js,它包含你网站的所有部分都没有改变。此外,为每个可以更改的窗口小部件创建一个widget1.bundle.js等。导入index.html上的所有内容。然后,将您的Web服务器配置为永远不会缓存较小的包(widget1等)。每当用户进入网站时,它将再次下载这些小部件,有效地更新它们。如果你想要更加花哨,你可以提供一个API与每个小部件的当前版本,并在小部件包上添加一个额外的字段与版本,以便您可以定期检查组件是否是最新的,在用户暂时没有重新加载页面的事件。如果您发现过时的组件,只需强制重新加载,浏览器将确保获取最新版本。
我知道这与你的目标完全不同,但如果它对你的特定情况有好处,我相信它会更简单,更容易实现并保证稳定性,更易于维护,整体更好解决方案比解析html并自己处理所有请求。
答案 2 :(得分:-1)
为什么不使用浏览器DOMParser API将HTML解析为屏幕外/分离的DOM,然后遍历该DOM并使用React.createElement()
来构建React的DOM?像
let str = "... your HTML ..."
function traverse(node) {
let children = []
for (let i = 0; i < node.children.length; i++)
children.push(traverse(node.children.item(i)))
return React.createElement(node.localName, null, children)
// or maybe use the following instead (React's API doc
// isn't very clear about this):
// return React.createElement(node.localName, null, ...children)
}
let reactElementForStr =
traverse(new DOMParser().parseFromString(str, 'text/html'))
请注意,我对React的内部工作方式只有一点知识,并且根本没有对此进行过测试。
答案 3 :(得分:-1)
最简单的方法是使用Dangerously Set innerHTML
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
但是这需要付出代价,将HTML字符串嵌入到模板中会动态导致安全违规,这就是为什么它具有奇怪的语法__html和一个可怕的名称dangerouslySetInnerHTML。如果您正在使用此功能,请确保您清理输入参数以防止任何XSS吸引。 您也可以使用iframe
从下面的笔(推荐)检查完整的实施 https://codepen.io/varmakarthik12/pen/zaOzPw