You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Typescript项目中注入外部HTML/JS渲染Plotly图表的方案问询

React + TypeScript 注入带JS的Plotly HTML内容解决方案

你遇到的JS不执行问题是React的内置安全机制导致的:dangerouslySetInnerHTML 出于XSS防护考虑,不会执行插入内容中包含的任何JS代码,因此只能渲染静态HTML元素,Plotly的绘图逻辑无法触发。

以下是不同场景下的可行方案,推荐优先级从高到低:

方案1:iframe托管(最推荐)

完全隔离主应用和注入内容的执行上下文,无全局变量污染风险,原生支持HTML内JS执行,适配任意返回的完整HTML内容。

import { useRef, useEffect } from 'react';

interface PlotlyIframeProps {
  htmlContent: string;
  height?: string;
  width?: string;
}

const PlotlyIframe = ({ htmlContent, height = '500px', width = '100%' }: PlotlyIframeProps) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);

  useEffect(() => {
    if (!iframeRef.current) return;
    const iframeDoc = iframeRef.current.contentDocument || iframeRef.current.contentWindow?.document;
    if (!iframeDoc) return;
    // 把完整HTML写入iframe
    iframeDoc.open();
    iframeDoc.write(htmlContent);
    iframeDoc.close();
  }, [htmlContent]);

  return <iframe ref={iframeRef} height={height} width={width} frameBorder="0" title="Plotly图表" />;
};

export default PlotlyIframe;

使用时直接把API拿到的完整HTML字符串传给组件的htmlContent参数即可。

方案2:手动解析执行JS(无iframe场景使用)

如果不能使用iframe,可手动拆分HTML中的DOM和JS分别处理,注意:仅在你完全信任API返回内容的场景下使用,避免XSS攻击风险。

import { useRef, useEffect } from 'react';

interface PlotlyRendererProps {
  rawHtml: string;
}

const PlotlyRenderer = ({ rawHtml }: PlotlyRendererProps) => {
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!containerRef.current || !rawHtml) return;
    const parser = new DOMParser();
    const doc = parser.parseFromString(rawHtml, 'text/html');
    // 提取所有脚本内容
    const scripts = doc.querySelectorAll('script');
    const scriptCodes: string[] = [];
    scripts.forEach(script => {
      if (script.textContent) {
        scriptCodes.push(script.textContent);
      }
      script.remove();
    });
    // 渲染DOM结构
    containerRef.current.innerHTML = doc.body.innerHTML;
    // 手动执行脚本
    scriptCodes.forEach(code => {
      eval(code);
    });
  }, [rawHtml]);

  return <div ref={containerRef} />;
};

export default PlotlyRenderer;

补充注意:如果返回的HTML依赖外部Plotly资源,需要提前在主应用全局引入Plotly.js,否则执行JS时会出现Plotly is not defined报错。

方案3:优化结构彻底规避注入风险(可配合后端调整时最优)

如果后端可以修改返回格式,优先让接口直接返回Plotly绘图的三个核心参数:data、layout、config,无需注入HTML,直接使用react-plotly.js渲染,性能更好,完全无安全风险。


内容的提问来源于stack exchange,提问作者k3nz0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 14:36:02