如何在Angular7 应用程序中使用一个GWT 应用程序作为一个组件?
How to use a GWT application in Angular 7 application as a component?
我有一个 Angular 7 应用程序,我想将单页 GWT 应用程序用作组件。使用该 GWT 应用程序作为组件的原因是我不希望我的 GWT 应用程序在我使用 Angular 路由导航到该应用程序(或页面)时一次又一次地重新加载。
这是我尝试过的:
首先,我将该 GWT 项目的编译二进制文件放在我的 Angular 应用程序的资产文件夹中。然后我将所有内容放在我的 Angular 应用程序的 component.html 文件中的 index.html 标签下。然后添加一个按钮并在其点击事件上应用路由器导航,以便点击该按钮将导航到我的 Angular 应用程序的组件页面。
我将 GWT 应用程序嵌入到 Angular 组件的 iFrame 中。但是我观察到,在通过路由导航到该页面时,每当我使用路由来回导航到该页面和另一个 Angular 页面时,它就会一次又一次地重新加载。
我还在angular.json文件的scripts参数中添加了GWT应用程序所有需要的javascript文件的路径并在tsconfig.json.
中将allowJs参数修改为true
我知道在构建 Angular 项目时会创建 main.js 文件,其中包含所有组件(包括它们的路由)的已编译 JS 代码。所以,我也想到了把GWT的主nocache.js文件转成TS文件,但是语法错误很多,就忽略了这个过程。
现在以我有限的知识,除了上面指定的那些,我想不出任何解决方案,我真的陷入了这种情况,无法继续我的项目。
那么,谁能帮我找到解决方案?我也不确定是否可以这样做。
如果我理解正确的话,您想在导航到其他路由时保持 angular 组件(页面)处于活动状态。
Angular 默认情况下,路由会在您每次转到另一个组件时销毁该组件,并在您 return 访问它时再次创建它。这就是它每次都加载的原因。
您需要做的是实现一个自定义 RouteReuseStrategy 来让您的组件保持活动状态。
这是一个非常简单的实现,假设您的 GWT 应用程序组件具有路由 'gwt'。
export class GwtRouteReuseStrategy extends RouteReuseStrategy {
private cache: {[key: string]: DetachedRouteHandle} = {};
public shouldDetach(route: ActivatedRouteSnapshot): boolean {
return route.url.join('/') === 'gwt';
}
public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.cache[route.url.join('/')] = handle;
}
public shouldAttach(route: ActivatedRouteSnapshot): boolean {
return this.cache[route.url.join('/')] != null;
}
public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
return this.cache[route.url.join('/')];
}
public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.url.join('/') === 'gwt';
}
}
您需要在应用程序模块提供程序中提供策略,以便路由器使用它。
@NgModule({
…,
providers: [
{ provide: RouteReuseStrategy, useClass: GwtRouteReuseStrategy}
],
})
export class AppModule {
}
这里还有一个 link 到 StackBlitz 的示例,您可以在其中看到它的工作原理。打开控制台可以看到 'GwtComponent' 在您离开时没有被销毁。
我正在添加另一个答案来解决第一个答案的评论中提到的问题。问题是,即使 RouteReuseStrategy 使组件保持活动状态,组件内的 iframe
仍然会重新加载。这可能是因为 Angular 将它从页面 DOM 分离然后重新附加它。
一个变通的解决方案是让带有 iframe
的组件在您的主应用程序组件中始终处于活动状态,并在您导航到另一个页面时隐藏它。如果您导航到要显示它的路线,则再次显示它。您可以使用 Router events.
这是一个实施此解决方法的示例应用程序组件。 gwt
组件是带有 iFrame 的组件。
模板:
<h2><a routerLink="/main">Main</a></h2>
<h2><a routerLink="/gwt">Gwt</a></h2>
<gwt [hidden]="!gwtVisible"></gwt>
<router-outlet [hidden]="gwtVisible"></router-outlet>
代码:
export class AppComponent {
gwtVisible = false;
constructor(router: Router) {
router.events.subscribe((routerEvent) => {
if (routerEvent instanceof NavigationEnd) {
this.gwtVisible = routerEvent.url === '/gwt';
}
});
}
}
正如您从代码中看到的那样,当您导航到 /gwt
路由并显示 gwt
组件时,应用程序组件会隐藏主要内容,否则它会隐藏它并正常显示其他内容router-outlet
.
在我定义的路线中,它导航到一个空组件只是为了让路线 /gwt
有一些东西。
const routes: Routes = [
{ path: '', redirectTo: 'main', pathMatch: 'full' },
{ path: 'main', component: MainComponent },
{ path: 'gwt', component: EmptyComponent }
];
我还创建了一个带有工作示例的 StackBlitz。
我有一个 Angular 7 应用程序,我想将单页 GWT 应用程序用作组件。使用该 GWT 应用程序作为组件的原因是我不希望我的 GWT 应用程序在我使用 Angular 路由导航到该应用程序(或页面)时一次又一次地重新加载。
这是我尝试过的:
首先,我将该 GWT 项目的编译二进制文件放在我的 Angular 应用程序的资产文件夹中。然后我将所有内容放在我的 Angular 应用程序的 component.html 文件中的 index.html 标签下。然后添加一个按钮并在其点击事件上应用路由器导航,以便点击该按钮将导航到我的 Angular 应用程序的组件页面。
我将 GWT 应用程序嵌入到 Angular 组件的 iFrame 中。但是我观察到,在通过路由导航到该页面时,每当我使用路由来回导航到该页面和另一个 Angular 页面时,它就会一次又一次地重新加载。
我还在angular.json文件的scripts参数中添加了GWT应用程序所有需要的javascript文件的路径并在tsconfig.json.
中将allowJs参数修改为true
我知道在构建 Angular 项目时会创建 main.js 文件,其中包含所有组件(包括它们的路由)的已编译 JS 代码。所以,我也想到了把GWT的主nocache.js文件转成TS文件,但是语法错误很多,就忽略了这个过程。
现在以我有限的知识,除了上面指定的那些,我想不出任何解决方案,我真的陷入了这种情况,无法继续我的项目。
那么,谁能帮我找到解决方案?我也不确定是否可以这样做。
如果我理解正确的话,您想在导航到其他路由时保持 angular 组件(页面)处于活动状态。
Angular 默认情况下,路由会在您每次转到另一个组件时销毁该组件,并在您 return 访问它时再次创建它。这就是它每次都加载的原因。 您需要做的是实现一个自定义 RouteReuseStrategy 来让您的组件保持活动状态。
这是一个非常简单的实现,假设您的 GWT 应用程序组件具有路由 'gwt'。
export class GwtRouteReuseStrategy extends RouteReuseStrategy {
private cache: {[key: string]: DetachedRouteHandle} = {};
public shouldDetach(route: ActivatedRouteSnapshot): boolean {
return route.url.join('/') === 'gwt';
}
public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
this.cache[route.url.join('/')] = handle;
}
public shouldAttach(route: ActivatedRouteSnapshot): boolean {
return this.cache[route.url.join('/')] != null;
}
public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
return this.cache[route.url.join('/')];
}
public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.url.join('/') === 'gwt';
}
}
您需要在应用程序模块提供程序中提供策略,以便路由器使用它。
@NgModule({
…,
providers: [
{ provide: RouteReuseStrategy, useClass: GwtRouteReuseStrategy}
],
})
export class AppModule {
}
这里还有一个 link 到 StackBlitz 的示例,您可以在其中看到它的工作原理。打开控制台可以看到 'GwtComponent' 在您离开时没有被销毁。
我正在添加另一个答案来解决第一个答案的评论中提到的问题。问题是,即使 RouteReuseStrategy 使组件保持活动状态,组件内的 iframe
仍然会重新加载。这可能是因为 Angular 将它从页面 DOM 分离然后重新附加它。
一个变通的解决方案是让带有 iframe
的组件在您的主应用程序组件中始终处于活动状态,并在您导航到另一个页面时隐藏它。如果您导航到要显示它的路线,则再次显示它。您可以使用 Router events.
这是一个实施此解决方法的示例应用程序组件。 gwt
组件是带有 iFrame 的组件。
模板:
<h2><a routerLink="/main">Main</a></h2>
<h2><a routerLink="/gwt">Gwt</a></h2>
<gwt [hidden]="!gwtVisible"></gwt>
<router-outlet [hidden]="gwtVisible"></router-outlet>
代码:
export class AppComponent {
gwtVisible = false;
constructor(router: Router) {
router.events.subscribe((routerEvent) => {
if (routerEvent instanceof NavigationEnd) {
this.gwtVisible = routerEvent.url === '/gwt';
}
});
}
}
正如您从代码中看到的那样,当您导航到 /gwt
路由并显示 gwt
组件时,应用程序组件会隐藏主要内容,否则它会隐藏它并正常显示其他内容router-outlet
.
在我定义的路线中,它导航到一个空组件只是为了让路线 /gwt
有一些东西。
const routes: Routes = [
{ path: '', redirectTo: 'main', pathMatch: 'full' },
{ path: 'main', component: MainComponent },
{ path: 'gwt', component: EmptyComponent }
];
我还创建了一个带有工作示例的 StackBlitz。