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

如何在ReactJS的render()中加载含document.write的cricruns组件脚本

在React的render()中加载使用document.write的第三方组件

嘿,这个问题我之前处理过,用document.write的第三方脚本在React环境里确实有点麻烦——毕竟React的虚拟DOM渲染机制和直接操作原生DOM的逻辑不太兼容。下面给你两个可行的实现方案,分别适配类组件和函数组件:

方案一:类组件实现(使用componentDidMount)

我们可以在组件挂载完成后,动态创建脚本标签,同时拦截document.write方法,把脚本输出的内容定向到我们指定的容器里,避免它乱插DOM或者覆盖页面:

import React, { Component } from 'react';

class CricrunsWidget extends Component {
  componentDidMount() {
    const widgetContainer = this.widgetContainer;
    // 先保存原生的document.write方法,后面要恢复
    const originalDocumentWrite = document.write;

    // 重写document.write,让它把内容插入到我们的组件容器中
    document.write = function(htmlContent) {
      widgetContainer.innerHTML = htmlContent;
      // 内容插入完成后,恢复原生方法,避免影响其他代码
      document.write = originalDocumentWrite;
    };

    // 动态创建并加载目标脚本
    const scriptTag = document.createElement('script');
    scriptTag.src = '//www.cricruns.com/system/application/views/widgetBase/wid_300_200_1.js';
    scriptTag.type = 'text/javascript';
    document.body.appendChild(scriptTag);
  }

  render() {
    // 这里用ref获取容器DOM节点,供后面插入内容用
    return <div ref={el => this.widgetContainer = el} />;
  }
}

export default CricrunsWidget;

方案二:函数组件实现(使用useEffect + useRef)

如果你用的是React Hooks,这个方案更适合:

import React, { useEffect, useRef } from 'react';

const CricrunsWidget = () => {
  // 用useRef获取组件容器的DOM引用
  const widgetContainer = useRef(null);

  useEffect(() => {
    if (!widgetContainer.current) return;

    const originalDocumentWrite = document.write;
    // 拦截document.write,定向到我们的容器
    document.write = function(htmlContent) {
      widgetContainer.current.innerHTML = htmlContent;
      document.write = originalDocumentWrite;
    };

    // 创建脚本标签
    const scriptTag = document.createElement('script');
    scriptTag.src = '//www.cricruns.com/system/application/views/widgetBase/wid_300_200_1.js';
    scriptTag.type = 'text/javascript';

    // 脚本加载完成后的可选清理
    scriptTag.onload = () => {
      // 如果不需要保留脚本标签,可以在这里移除它
      // document.body.removeChild(scriptTag);
    };

    document.body.appendChild(scriptTag);

    // 组件卸载时的清理函数:恢复原生document.write,移除脚本标签
    return () => {
      document.write = originalDocumentWrite;
      document.body.removeChild(scriptTag);
    };
  }, []); // 空依赖数组确保只执行一次

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

export default CricrunsWidget;

关键注意点

  • 为什么不能在render里直接处理?因为React的render是纯函数,不允许有副作用(比如加载脚本、操作DOM),必须在组件生命周期的副作用阶段(componentDidMount或useEffect)处理。
  • 拦截document.write是核心:原脚本用这个方法输出组件内容,直接执行会破坏React的DOM结构,所以我们把输出定向到自己的容器里。
  • 一定要做清理:组件卸载时恢复原生的document.write方法,移除动态创建的脚本标签,避免内存泄漏和影响其他组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:11:33