如何将React Web组件集成到Angular并传递Props
将React组件集成到Angular应用并传递Props的两种方案
方案一:将React组件转为Web Component(Custom Element)
这种方式遵循Web标准,Angular可以直接像原生标签一样使用,适合需要跨框架复用的场景。
步骤1:准备React组件及依赖
在单独的React项目(或Angular项目内的子目录)编写目标组件,安装必要工具:
npm install react react-dom @babel/core @babel/preset-react babel-loader webpack webpack-cli @webcomponents/webcomponentsjs --save-dev
步骤2:编写React组件
创建MyReactComponent.jsx:
import React from 'react'; export default function MyReactComponent({ name, onButtonClick }) { return ( <div> <h1>Hello, {name}!</h1> <button onClick={() => onButtonClick('React按钮被点击')}>点击我</button> </div> ); }
步骤3:封装为Web Component
创建react-web-component-wrapper.js,将React组件包裹为自定义元素:
import React from 'react'; import ReactDOM from 'react-dom/client'; import MyReactComponent from './MyReactComponent'; class ReactWebComponent extends HTMLElement { // 声明需要监听的属性(对应React组件的Props) static get observedAttributes() { return ['name']; } constructor() { super(); this.attachShadow({ mode: 'open' }); this.handleButtonClick = this.handleButtonClick.bind(this); } // 属性变化时重新渲染组件 attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { this.render(); } } // 元素挂载到DOM时渲染 connectedCallback() { this.render(); } // 将React组件的回调转为自定义事件,供Angular监听 handleButtonClick(message) { this.dispatchEvent(new CustomEvent('button-click', { detail: message })); } // 渲染React组件 render() { const name = this.getAttribute('name'); const root = ReactDOM.createRoot(this.shadowRoot); root.render( <MyReactComponent name={name} onButtonClick={this.handleButtonClick} /> ); } } // 注册自定义元素 customElements.define('my-react-component', ReactWebComponent);
步骤4:打包Web Component
创建webpack.config.js:
const path = require('path'); module.exports = { entry: './react-web-component-wrapper.js', output: { filename: 'react-web-component.js', path: path.resolve(__dirname, 'dist'), library: 'ReactWebComponent', libraryTarget: 'umd', }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react'], }, }, }, ], }, externals: { react: 'React', 'react-dom': 'ReactDOM', }, };
执行打包命令:
npx webpack --mode production
步骤5:在Angular中集成
- 将打包后的
react-web-component.js复制到Angular项目的src/assets目录。 - 修改
angular.json,添加依赖脚本:
"scripts": [ "node_modules/react/umd/react.production.min.js", "node_modules/react-dom/umd/react-dom.production.min.js", "src/assets/react-web-component.js" ]
- 在
app.module.ts中允许自定义元素:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule], providers: [], bootstrap: [AppComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA] // 必须添加,否则Angular会识别未知标签为错误 }) export class AppModule { }
- 在Angular组件模板中使用并传递Props:
// app.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <my-react-component [attr.name]="userName" (button-click)="handleReactEvent($event)" ></my-react-component> `, }) export class AppComponent { userName = 'Angular用户'; handleReactEvent(event: CustomEvent) { console.log('从React接收的消息:', event.detail); } }
注意:如果需要传递复杂对象Props,需将对象转为JSON字符串传递,在Web Component内部解析:
<!-- Angular模板 --> <my-react-component [attr.user-data]="userData | json" ></my-react-component>
// Web Component的render方法中解析 const userData = JSON.parse(this.getAttribute('user-data') || '{}');
方案二:直接在Angular组件中挂载React组件
这种方式无需额外打包,直接在Angular项目中引入React组件并手动挂载,适合简单场景或需要频繁传递复杂Props的情况。
步骤1:安装React依赖
在Angular项目中执行:
npm install react react-dom @types/react @types/react-dom --save
步骤2:编写React组件
在Angular项目内创建src/app/react-components/MyReactComponent.tsx:
import React from 'react'; // 定义Props类型 interface MyReactComponentProps { name: string; onButtonClick: (message: string) => void; } export default function MyReactComponent({ name, onButtonClick }: MyReactComponentProps) { return ( <div> <h1>Hello, {name}!</h1> <button onClick={() => onButtonClick('React按钮被点击')}>点击我</button> </div> ); }
步骤3:在Angular组件中挂载React组件
修改app.component.ts:
import { Component, ElementRef, OnInit, OnDestroy, ViewChild } from '@angular/core'; import React from 'react'; import ReactDOM from 'react-dom/client'; import MyReactComponent from './react-components/MyReactComponent'; @Component({ selector: 'app-root', template: `<div #reactContainer></div>`, }) export class AppComponent implements OnInit, OnDestroy { // 获取挂载容器的DOM引用 @ViewChild('reactContainer', { static: true }) reactContainer!: ElementRef<HTMLDivElement>; private reactRoot: ReactDOM.Root | null = null; userName = 'Angular用户'; ngOnInit() { // 初始化React根节点并渲染组件 this.reactRoot = ReactDOM.createRoot(this.reactContainer.nativeElement); this.renderReactComponent(); } ngOnDestroy() { // 组件销毁时卸载React组件,避免内存泄漏 this.reactRoot?.unmount(); } // 渲染React组件并传递Props private renderReactComponent() { this.reactRoot?.render( React.createElement(MyReactComponent, { name: this.userName, onButtonClick: (message) => this.handleReactEvent(message) }) ); } handleReactEvent(message: string) { console.log('从React接收的消息:', message); } }
注意:如果React组件的Props需要响应Angular的变量变化,可在Angular的ngOnChanges钩子中重新调用renderReactComponent()方法。
内容的提问来源于stack exchange,提问作者parmeshwar chavan
相关产品推荐
相关产品推荐

