react应用程序接收到一个可视化代码,我使用unescape函数以字符串形式获取HTML代码。该字符串有一个div
标签与可视化的id和script
标签组成的javascript生成可视化。
import React from "react";
import parse from "html-react-parser";
export default function App() {
// This code is received from the backend
const vizCode =
"%3Cdiv%20id%3D'chartdiv_1614071920146'%3E%3C%2Fdiv%3E%3Cscript%20type%3D'text%2Fjavascript'%3E%20var%20width_1614071920146%20%3D%20700%3Bvar%20height_1614071920146%20%3D%20700%3Bvar%20chart_1614071920146%20%3D%20c3.generate(%7Bbindto%3A%20'%23chartdiv_1614071920146'%2C%20size%3A%20%7B%20width%3A%20(width_1614071920146%20-%2020)%2C%20height%3A%20(height_1614071920146%20-%2020)%20%7D%2C%20data%3A%20%7Bcolumns%3A%20%5B%20%5B'%20'%2C%201.0%2C%201.0%2C%203.0%2C%205.0%2C%205.0%5D%20%5D%2C%20type%3A%20'spline'%7D%2C%20legend%3A%20%7Bshow%3Afalse%7D%2C%20axis%3A%20%7B%20x%3A%20%7B%20type%3A%20'category'%2C%20categories%3A%20%5B'New%20Course'%2C'group%20course%201'%2C'Testkurs%20'%2C'test_course'%2C'Moodle4CollaborativeMOOCs'%5D%20%7D%20%7D%7D)%3B%3C%2Fscript%3E";
const unescapedVizCode = unescape(vizCode);
console.log(unescapedVizCode);
// Output -> <div id='chartdiv_1614071920146'></div><script type='text/javascript'> var width_1614071920146 = 700;var height_1614071920146 = 700;var chart_1614071920146 = c3.generate({bindto: '#chartdiv_1614071920146', size: { width: (width_1614071920146 - 20), height: (height_1614071920146 - 20) }, data: {columns: [ [' ', 1.0, 1.0, 3.0, 5.0, 5.0] ], type: 'spline'}, legend: {show:false}, axis: { x: { type: 'category', categories: ['New Course','group course 1','Testkurs ','test_course','Moodle4CollaborativeMOOCs'] } }});</script>
let objectData = parse(unescapedVizCode);
let divData = objectData[0];
let scriptData = objectData[1].props.dangerouslySetInnerHTML.__html;
return (
<div className="App">
{objectData}
</div>
);
}
这里我提供了codesandbox链接
我使用dangerouslySetInnerHtml
显示可视化,但无法可视化图表。我在公共文件夹中添加了test.html,以便在浏览器中显示可视化效果。如有任何帮助,不胜感激。
React/JSX不处理脚本标记。你必须显式加载它。我建议你在组件可用的时候使用钩子。
useEffect(() => {
const script = document.createElement('script');
script.innerHTML = scriptData;
document.getElementById('root').appendChild(script);
return () => {
document.getElementById('root').removeChild(script);
};
}, []);
这里的工作示例:https://codesandbox.io/s/render-c3d3-charts-in-react-forked-4xkt9?file=/src/App.js
顺便说一句。请不要使用'unescape',不推荐使用。请使用' decodeuriccomponent '。
好吧,这个答案是你想要的,但我不得不说:只有在你100%知道vizCode来自哪里并且它可以被信任的情况下才使用这个!一定要找出不应该使用eval
的原因你的问题是,脚本内容没有被浏览器执行。我试过你的沙盒,当我添加
时,它立即工作了eval(scriptData)
这是为我工作的整个代码:
export default function App() {
// This code is received from the backend
const vizCode =
"%3Cdiv%20id%3D'chartdiv_1614071920146'%3E%3C%2Fdiv%3E%3Cscript%20type%3D'text%2Fjavascript'%3E%20var%20width_1614071920146%20%3D%20700%3Bvar%20height_1614071920146%20%3D%20700%3Bvar%20chart_1614071920146%20%3D%20c3.generate(%7Bbindto%3A%20'%23chartdiv_1614071920146'%2C%20size%3A%20%7B%20width%3A%20(width_1614071920146%20-%2020)%2C%20height%3A%20(height_1614071920146%20-%2020)%20%7D%2C%20data%3A%20%7Bcolumns%3A%20%5B%20%5B'%20'%2C%201.0%2C%201.0%2C%203.0%2C%205.0%2C%205.0%5D%20%5D%2C%20type%3A%20'spline'%7D%2C%20legend%3A%20%7Bshow%3Afalse%7D%2C%20axis%3A%20%7B%20x%3A%20%7B%20type%3A%20'category'%2C%20categories%3A%20%5B'New%20Course'%2C'group%20course%201'%2C'Testkurs%20'%2C'test_course'%2C'Moodle4CollaborativeMOOCs'%5D%20%7D%20%7D%7D)%3B%3C%2Fscript%3E";
const unescapedVizCode = unescape(vizCode);
console.log(unescapedVizCode);
let objectData = parse(unescapedVizCode);
let divData = objectData[0];
let scriptData = objectData[1].props.dangerouslySetInnerHTML.__html;
useEffect(()=>{
eval(scriptData)
}, [scriptData])
return (
<div className="App">
{objectData}
</div>
);
}
我不确定它是否满足您的要求,但您可以使用window.open
在iFrame
或新选项卡中呈现HTML代码。
在iFrame
中打开使用以下代码:
const unescapedVizCode = unescape(vizCode);
window.open(unescapedVizCode, "myFrame");
return (
<div className="App">
<iframe name="myFrame"></iframe>
{objectData}
</div>
);
或者您可以在新选项卡中打开:
const unescapedVizCode = unescape(vizCode);
window.open(unescapedVizCode, "_blank");
尝试:
let objectData = parse(`<div className="App">${unescapedVizCode}</div>`);
return objectData;