reactjs - 在 angularjs 应用程序中重用 react 应用程序
问题描述
我想在 angularjs 应用程序中完全重用一个小型反应应用程序。有没有办法达到同样的效果。我已经使用 ngReact 在 Angular js 中加载反应,它工作正常。但是,我如何完全重用应用程序而无需太多更改。
注意:我知道这是一种不好的做法,但由于遗留代码,必须实现它。
任何线索表示赞赏。蒂亚!
解决方案
解决方案实施
包.json
"dependencies": {
...
"react": "^16.12.0",
"react-dom": "^16.12.0",
...
},
"devDependencies": {
...
"@types/react": "^16.9.17",
"@types/react-dom": "^16.9.4",
...
}
tsconfig.json
{
...
"jsx": "react",
...
}
包装器组件
包装器负责检测更改并重新渲染被包装的 React 组件,使其 props 生效,最终在包装器被销毁时卸载被包装的组件。
MyReactComponentWrapper.tsx
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnDestroy,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { MyReactComponent } from 'src/components/my-react-component/MyReactComponent';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const containerElementName = 'myReactComponentContainer';
@Component({
selector: 'app-my-component',
template: `<span #${containerElementName}></span>`,
styleUrls: ['./MyReactComponent.scss'],
encapsulation: ViewEncapsulation.None,
})
export class MyComponentWrapperComponent implements OnChanges, OnDestroy, AfterViewInit {
@ViewChild(containerElementName, {static: false}) containerRef: ElementRef;
@Input() public counter = 10;
@Output() public componentClick = new EventEmitter<void>();
constructor() {
this.handleDivClicked = this.handleDivClicked.bind(this);
}
public handleDivClicked() {
if (this.componentClick) {
this.componentClick.emit();
this.render();
}
}
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
ngAfterViewInit() {
this.render();
}
ngOnDestroy() {
ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement);
}
private render() {
const {counter} = this;
ReactDOM.render(<div className={'i-am-classy'}>
<MyReactComponent counter={counter} onClick={this.handleDivClicked}/>
</div>, this.containerRef.nativeElement);
}
}
MyReactComponent.tsx
import * as React from 'react';
import { FunctionComponent, useEffect, useRef, useState } from 'react';
import './MyReactComponent.scss';
export interface IMyComponentProps {
counter: number;
onClick?: () => void;
}
export const MyReactComponent: FunctionComponent<IMyComponentProps> = (props: IMyComponentProps) => {
const timerHandle = useRef<number | null>(null);
const [stateCounter, setStateCounter] = useState(42);
useEffect(() => {
timerHandle.current = +setInterval(() => {
setStateCounter(stateCounter + 1);
}, 2500);
return () => {
if (timerHandle.current) {
clearInterval(timerHandle.current);
timerHandle.current = null;
}
};
});
const {counter: propsCounter, onClick} = props;
const handleClick = () => {
if (onClick) {
onClick();
}
};
return <div className={`my-graph-component`}>
<div className={'comp-props'}>Props counter: {propsCounter}
<span onClick={handleClick}
className={'increase-button'}>click to increase</span>
</div>
<div className={'comp-state'}>State counter: {stateCounter}</div>
</div>;
};
推荐阅读
- php - 有没有办法在 Wordpress 导入/导出中包含 acf 图像
- officer - 漏洞?在定义 id 时,它会在不应该的时候说越界
- java - firebase 实时数据库验证规则
- c++ - 计数器不计算所有不同的元音
- java - 有没有办法优化这种方法?
- machine-learning - Pyspark 中的过采样或 SMOTE
- c# - 如何使用 EntityFramework 6.2 将 DbFunctions/SqlFunctions 调用提取到可重用的扩展/方法中?
- javascript - 自动点击页面上的 div
- zeromq - 如何将 XMLRPC 软件移至 ZMQ?
- python - 如何从包含任何行中的特定值的数据框中删除列