我有一个Angular应用程序,我想在ReactJS中编写应用程序的某些部分。
如何将ReactJS应用程序注入现有的Angular应用程序中?我还需要组件的双向通信。
下面的所有代码都是最少的,无法在提出的步骤中显示问题。在GitHub上,您拥有完整的代码来解决问题,以下示例并不总是1:1,因为此代码已扩展。
要将ReactJS应用添加到现有的Angular应用中,您需要安装5个npm依赖项:react
,react-dom
:
npm install --save react
npm install --save react-dom
npm install --save-dev @types/react
npm install --save-dev @types/react-dom
npm install --save-dev @types/react-select
下一步-我们应该允许jsx
在.tsx
文件中使用模板,因此我们应该进行编辑tsconfig.json
并添加:
{
...
"compilerOptions": {
…
"jsx": "react"
}
如果使用WebStorm,则应重新启动项目,因为tslint会显示错误,直到重新启动。
为了保持结构清晰,我创建了以下目录结构:
angular /
ng-hero.component.ts // Component in Angular
react-renderer.component.ts // ReactJS renderer without communication
react /
react-application.tsx // React init application
react-hero.tsx // React hero component
app.component.html
app.component.ts
现在,您需要在Angular中创建特殊组件,该组件将负责嵌入ReactJS应用程序。我将调用此组件ReactRendererComponent
。这个组件非常简单,它只有一行模板行,带有的构造函数import Injector
和一行ngOnInit
:
@Component({
selector: 'app-react-renderer',
template: `<div class="react-container" id="react-renderer"></div>`
})
export class ReactRendererComponent implements OnInit {
constructor(public injector: Injector) { }
ngOnInit() {
ReactApplication.initialize('react-renderer', this.injector);
}
}
现在我们需要ReactApplication
在其中初始化ReactJS应用程序的组件:
interface IReactApplication {
injector: Injector;
}
class ReactApp extends React.Component<IReactApplication, any> {
constructor(props) {
super(props);
}
render() {
return (
<div className={'renderer'}>
<h2>ReactJS component: </h2>
<br/>
<ReactHero/>
</div>
);
}
}
export class ReactApplication {
static initialize(
containerId: string,
injector: Injector
) {
ReactDOM.render(
<ReactApp injector={injector}/>,
document.getElementById(containerId)
);
}
}
我们需要ReactHero
以下示例中使用的组件:
class ReactHero extends React.Component<any, any> {
constructor(props) {
super(props);
}
render() {
return (
<span>
<span>react-hero works!</span><br/>
<span>Don't have any data</span>
</span>
);
}
}
export default ReactHero;
在Angular App中,我们应该使用ReactRenderer
component,所以我们使用:
App.component data:
<hr>
<h2>This is Angular</h2>
<img width="100" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
<hr>
<!-- Without data binding -->
<app-react-renderer></app-react-renderer>
目前,我们有带有嵌入式ReactJS应用程序的Angular应用程序,但是没有任何通信。对您来说足够了吗?如果是的话,就这些了。如果您需要在两个应用程序之间进行任何形式的通信,请在下面为您介绍RxJS选项。
在此示例中,RxJS支持双向数据绑定。您可以获取此数据,并在ReactJS应用和Angular应用中使用它们以查看所有更改。这对于许多项目来说已经足够了,但是您可以使用不同的选项来获得这种双向通信,例如,可以对它们使用Redux。
为了清楚起见,下面我将提供此部分的完整目录结构:
angular /
hero.service.ts
ng-hero.component.ts // Component in Angular
react-bidirectional-renderer.component.ts // ReactJS renderer with bidirectional communication
model /
hero.ts // interface for Hero object
react-bidirectional
react-bidirectional-application.tsx // React init application with bidirectional communication
react-bidirectional-hero.tsx // React hero component with RxJS support
app.component.html
app.component.ts
首先,我们创建IHero
带有数据的接口:/model/hero.ts
export interface IHero {
name: string;
age: number;
}
在下一步中,我们创建angular/hero.service.ts
服务,以在应用程序的Angular部分中使用它:
@Injectable({
providedIn: 'root'
})
export class HeroService {
private heroes$: BehaviorSubject<IHero[]> = new BehaviorSubject([]);
constructor() {
}
addHeroes(hero: IHero) { // To add new hero
const actualHero = this.heroes$.value;
actualHero.push(hero);
this.heroes$.next(actualHero);
}
updateHeroAge(heroId: number, age: number) { // To update age of selected hero
const actualHero = this.heroes$.value;
actualHero[heroId].age = age;
this.heroes$.next(actualHero);
}
getHeroes$(): BehaviorSubject<IHero[]> { // To get BehaviorSubject and pass it into ReactJS
return this.heroes$;
}
}
然后app.component.ts
我们用数据初始化(Zeus和Poseidon):
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
public heroesObj$: BehaviorSubject<IHero[]>;
public heroes: IHero[];
constructor(private heroService: HeroService) {}
ngOnInit(): void {
this.heroService.getHeroes$().subscribe((res: IHero[]) => {
this.heroes = res;
});
this.heroesObj$ = this.heroService.getHeroes$();
this.initHeroes();
}
initHeroes() {
this.heroService.addHeroes({name: 'Zeus', age: 88});
this.heroService.addHeroes({name: 'Poseidon', age: 46});
}
}
在下一步中,我们应该准备应用程序的ReacJS部分,因此我们创建react-bidirectional/react-bidirectional- application.tsx
文件:
interface IReactBidirectionalApp {
injector: Injector;
heroes$: BehaviorSubject<IHero[]>; // We use this interface to grab RxJS object
}
class ReactBidirectionalApp extends React.Component<IReactBidirectionalApp, any> {
constructor(props) {
super(props);
this.state = {
heroes$: this.props.heroes$ // and we pass this data into ReactBidirectionalHero component
};
}
render() {
return (
<div className={'renderer'}>
<h2>ReactJS component (bidirectional data binding): </h2>
<ReactBidirectionalHero heroes$={this.state.heroes$}/>
</div>
);
}
}
export class ReactBidirectionalApplication {
static initialize(
containerId: string,
injector: Injector,
heroes$: BehaviorSubject<IHero[]>, // This is necessary to get RxJS object
) {
ReactDOM.render(
<ReactBidirectionalApp injector={injector} heroes$={heroes$}/>,
document.getElementById(containerId)
);
}
}
在下一步中,我们需要ReactBidirectionalHero
组件,因此我们将其创建:
interface IReactBidirectionalHero {
heroes$: BehaviorSubject<IHero[]>;
}
class ReactBidirectionalHero extends React.Component<IReactBidirectionalHero, any> {
constructor(props) {
super(props);
this.state = {
heroes: []
};
this.addAge = this.addAge.bind(this); // Register function to bump age
this.addHero = this.addHero.bind(this); // Register function to add new Hero
}
componentDidMount(): void {
// In componentDidMount we subscribe heroes$ object
this.props.heroes$.subscribe((res: IHero[]) => {
// and we pass this data into React State object
this.setState({heroes: res});
});
}
addAge(i: number) {
const temp = this.state.heroes;
temp[i].age = temp[i].age + 1;
// In this way we update RxJS object
this.props.heroes$.next( temp);
}
addHero() {
const temp = this.state.heroes;
temp.push({name: 'Atena', age: 31});
// In this way we update RxJS object
this.props.heroes$.next(temp);
}
render() {
// Hire we render RxJS part of application with addAge button and ADD ATENA button below
const heroes = this.state.heroes.map((hero: IHero, i) => {
return <span key={i}>{hero.name} - {hero.age} <button onClick={() => this.addAge(i)}>Add {hero.name} age</button><br/></span>;
});
return (
<span>
<span>react-hero works!</span><br/>
{heroes}
<br/>
<button onClick={this.addHero}>ADD ATENA</button>
</span>
);
}
}
export default ReactBidirectionalHero;
现在我们需要在Angular应用程序中初始化ReactJS应用程序,因此我们可以创建angular/react-bidirectional- renderer.component.ts
它-非常简单,与版本相比只有一个更改,而无需通信:
@Component({
selector: 'app-react-owc-renderer',
template: `<div class="react-container" id="react-owc-renderer"></div>`
})
export class ReactBidirectionalRendererComponent implements OnInit {
// Hire we get data from parent component, but of course we can also subscribe this data directly form HeroService if we prefer this way
@Input() heroes$: BehaviorSubject<IHero[]>;
constructor(public injector: Injector) { }
ngOnInit() {
// We add only one parameter into initialize function
ReactBidirectionalApplication.initialize('react-owc-renderer', this.injector, this.heroes$);
}
}
现在,我们应该进行一些更改ng-hero.component.ts
以查看所有效果:
@Component({
selector: 'app-ng-hero',
template: `
<div>
<span>ng-hero works!</span><br/>
<span *ngFor="let hero of heroes; let i = index;">{{hero.name}} - {{hero.age}} - <button (click)="addAge(i)">Add {{hero.name}} age</button><br/></span>
<br/>
<button (click)="addHero()">ADD AFRODITA</button>
</div>
`
})
export class NgHeroComponent implements OnInit {
public heroes: IHero[];
constructor(private heroService: HeroService) { }
ngOnInit() {
this.heroService.getHeroes$().subscribe((res: IHero[]) => {
this.heroes = res;
});
}
addAge(heroId: number) {
this.heroService.updateHeroAge(heroId, this.heroes[heroId].age + 1);
}
addHero() {
this.heroService.addHeroes({name: 'Afrodita', age: 23});
}
}
最后我们改变app.component.html
:
App.component data:
<hr>
<h2>This is Angular component: </h2>
<app-ng-hero></app-ng-hero>
<hr>
<!-- With bidirectional data binding-->
<app-react-owc-renderer [heroes$]="heroesObj$"></app-react-owc-renderer>
<hr>
一切都应该工作。如果您有任何问题,请随时提问。
您可以在GitHub上找到此解决方案的完整存储库。
如果您需要演示,请点击雇用。
我的应用程序是用Flatter和Firebase RTDB(数据库1)开发的。它是为IOS和Android构建的。 我有一个使用JS和Firebase RTDB(数据库2)开发的辅助应用程序。它是为Web创建的。 现在,我想从我的Flatter应用程序中写入数据库2。我应该一步一步地做什么? 我尝试使用以下方法应用添加多个项目: 但我不确定这是否是一个安全的过程,我不知道如何调用辅助数据库实例..
我正在尝试使用PostgreSQL数据库构建一个Ruby on Rails Web应用程序,并使用Hibernate使用H2数据库引擎构建一个Java应用程序。 我听说过JDBC、RMI和套接字,但我对这些一无所知。 问题是,我想使用web应用程序中的数据,使用本地数据库在其中进行一些处理,最后我想将更改上传到数据库,或者说我想在web数据库中创建新表,并立即在web中显示更改。 例如,我想让学生
本文向大家介绍将SAP SOAP WebService与Android应用程序连接,包括了将SAP SOAP WebService与Android应用程序连接的使用技巧和注意事项,需要的朋友参考一下 您正在像这样在URL中传递参数:http : //XXX.com/xyz/api/sap-client=100&sap-user=username&sap-password=xxxxx“ 取而代之的是
问题内容: 我已经用create-react- app构建了一个Todo应用。我正在使用的商店基于本地存储(对象窗口的JS属性)。现在,我创建了一个MySQL数据库,并希望连接到该数据库,因此状态将显示数据库中的值,并将通过操作进行更新。 我尝试使用db.js通过“节点”控制台连接到数据库并输出值。有用。 是否可以使用此脚本将应用程序的状态连接到数据库? 问题答案: 您无法直接连接它们。 在网络浏
我想将一个Angular应用程序部署到一个Azure静态Web应用程序.构建部分工作正常,但发布错误并说它找不到构建项目:目录位置:'dist'无效。无法检测到此目录。请验证您的部署配置文件是否反映了您的存储库结构。 这是用于发布应用程序的YAML,下面是屏幕截图。 静态Web App模板 因此,似乎我们没有使用正确的发布位置,但不确定使用什么。 以下是来自管道的 YAML: 构建的安格应用程式的
问题内容: 我已经在Eclipse中生成了Android项目,并且一切正常。我添加了一些事件按钮。现在,我正在尝试创建Mongo对象,但会引发错误。你有什么解决办法吗?是否可以同时连接这两个? 日志: 问题答案: 此驱动程序不支持Android。吉拉有一个未解决的问题。