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

如何在原生JavaScript中调用已部署的React组件(类似Partial View)

解决方案

现有方案失效原因

你当前直接拉取React应用完整HTML插入容器的方案行不通,核心原因有3个:

  • DOMParser解析出来的是包含<html>、<head>、<body>的完整文档结构,嵌套在div中不符合HTML规范,浏览器无法正常解析
  • 插入的HTML中的script标签不会被浏览器自动执行,React代码根本没有运行
  • 拉取到的静态资源路径是相对路径,插入当前页后会以当前页域名为准,导致资源加载失败

你要的类似ASP.NET MVC分部视图的效果完全可以实现,具体方案如下:

实现步骤

1. 调整React项目配置

你使用的是create-react-app脚手架,我们需要修改配置让项目输出可被外部调用的组件包,而不是独立单页应用:

  1. 安装@craco/craco用来修改CRA配置(不需要执行eject)
npm install @craco/craco --save-dev
  1. 项目根目录新建craco.config.js,配置如下:
module.exports = {
  webpack: {
    configure: (webpackConfig) => {
      // 关闭代码拆分,打包为单文件方便引入
      webpackConfig.optimization.splitChunks = {
        cacheGroups: {
          default: false,
        },
      };
      webpackConfig.optimization.runtimeChunk = false;
      // 配置输出为UMD格式,暴露全局对象
      webpackConfig.output.library = 'KitchenQuiz';
      webpackConfig.output.libraryTarget = 'umd';
      webpackConfig.output.filename = 'static/js/kitchen-quiz.js';
      webpackConfig.output.chunkFilename = 'static/js/[name].chunk.js';
      // 关闭文件名哈希,方便固定引用地址
      webpackConfig.plugins.forEach(plugin => {
        if (plugin.constructor.name === 'MiniCssExtractPlugin') {
          plugin.options.filename = 'static/css/kitchen-quiz.css';
        }
      });
      return webpackConfig;
    }
  }
}
  1. 修改package.json中的scripts命令,将react-scripts替换为craco:
"scripts": {
  "start": "craco start",
  "build": "craco build",
  "test": "craco test",
  "eject": "react-scripts eject"
}
  1. 修改React入口文件src/index.js,暴露渲染/卸载方法供外部调用:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 不要直接渲染到固定dom,改为暴露方法
window.KitchenQuiz = {
  // 渲染到指定容器
  render: (containerId, props = {}) => {
    const container = document.getElementById(containerId);
    if (container) {
      ReactDOM.render(<App {...props} />, container);
    }
  },
  // 卸载组件
  unmount: (containerId) => {
    const container = document.getElementById(containerId);
    if (container) {
      ReactDOM.unmountComponentAtNode(container);
    }
  }
}
  1. 执行npm run build打包,将打包后的产物部署到原路径http://phpstack-444580-2225309.cloudwaysapps.com/KitchenQuestionApp/即可。

2. 原生页面调用代码

替换你原来的XHR拉取逻辑,改为动态加载静态资源后调用渲染方法即可:

<div class="row clearfix">
    <div class="col-md-12" data-noedit data-module="quiz-module" data-module-desc="quiz" >
      <div id='quizid'>  
      </div>
    </div>
</div>
<script>
var docReady = function (fn) {
  var stateCheck = setInterval(function () {
    if (document.readyState !== 'complete') return;
    clearInterval(stateCheck);
    try { fn() } catch (e) { }
  }, 1);
};
docReady(function () {
  // 加载组件样式
  const cssLink = document.createElement('link');
  cssLink.rel = 'stylesheet';
  cssLink.href = 'http://phpstack-444580-2225309.cloudwaysapps.com/KitchenQuestionApp/static/css/kitchen-quiz.css';
  document.head.appendChild(cssLink);

  // 加载组件脚本
  const script = document.createElement('script');
  script.src = 'http://phpstack-444580-2225309.cloudwaysapps.com/KitchenQuestionApp/static/js/kitchen-quiz.js';
  script.onload = function () {
    // 加载完成后渲染到quizid容器
    window.KitchenQuiz.render('quizid');
  }
  document.body.appendChild(script);
});
</script>

注意事项

  • 如果你的React组件中使用了BrowserRouter,请替换为HashRouter,或者给Router设置basename="/KitchenQuestionApp",避免路由和当前页面路径冲突
  • 如果原生页面和React组件部署域名不同,需要在React部署的服务器配置静态资源跨域访问权限,避免资源加载被浏览器拦截

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:54:03