Angular 和 AngularJS 混合应用程序路由:Angular 组件作为子状态未呈现
Angular and AngularJS Hybrid Application Routing: Angular component as child state not rendering
首先对项目和一般设置做一些简短的介绍。
它是一个 Angular/Angular JS 应用程序。我几周前集成了 Angular。与许多使用 UpgradeModule 的不同教程相比,我实际上不得不使用 downgradeModule - 项目非常大,UpgradeModule 导致了很多性能问题。
有一个总体父状态(称为应用程序),我希望 Angular 组件成为它的子组件。根据文档,这应该是可能的 (https://github.com/ui-router/angular-hybrid#limitations)
Limitations:
We currently support routing either Angular (2+) or AngularJS (1.x) components into an AngularJS (1.x) ui-view. However, we do not support routing AngularJS (1.x) components into an Angular (2+) ui-view.
If you create an Angular (2+) ui-view, then any nested ui-view must also be Angular (2+).
Because of this, apps should be migrated starting from leaf states/views and work up towards the root state/view.
一般设置如下所示(简化):
app.module.ng1.ts
import { AppModule } from './app.module';
const bootstrapFn: any = (extraProviders: Array<StaticProvider>): any => {
return platformBrowserDynamic(extraProviders).bootstrapModule(AppModule);
};
const downgradedModule: any = downgradeModule(bootstrapFn);
const appModule: angular.IModule = angular
.module('app', [
downgradedModule,
// other project modules
]);
app.module.ts
@NgModule({
imports: [
BrowserModule,
UIRouterUpgradeModule.forChild(),
],
declarations: [
AccountNg2Component,
],
providers: [
],
entryComponents: [
AccountNg2Component,
],
})
class AppModule {
public ngDoBootstrap(): void {}
}
export { AppModule };
TheAccountNg2Component 是我真正想去的那个。 account.component.ts
@Component({
selector: 'account',
template,
})
class AccountNg2Component {
@Input() public user: any;
constructor() {}
}
export { AccountNg2Component };
有一个父应用程序状态,我希望 AccountNg2Component 成为它的子级。状态配置如下所示:
$stateProvider
.state({
parent: 'app',
name: 'account',
url: '/account',
component: AccountNg2Component,
});
无论我尝试什么,都会导致以下两个错误:
Transition Rejection($id: 0 type: 6, message: The transition errored, detail: TypeError: Cannot read property 'when' of undefined)
TypeError: Cannot read property 'when' of undefined
at Ng2ViewConfig.load (views.js:47)
at eval (views.js:19)
at Array.map (<anonymous>)
at loadEnteringViews (views.js:19)
at invokeCallback (transitionHook.js:104)
at TransitionHook.invokeHook (transitionHook.js:116)
at eval (transitionHook.js:58)
at processQueue (angular.js:17169)
at eval (angular.js:17217)
at Scope.$digest (angular.js:18352)
at Scope.$apply (angular.js:18649)
at eval (angular.js:18952)
at completeOutstandingRequest (angular.js:6428)
at eval (angular.js:6707)
at ZoneDelegate.invokeTask (zone.js:420)
at Object.onInvokeTask (core.js:4961)
at ZoneDelegate.invokeTask (zone.js:419)
at Zone.runTask (zone.js:187)
at ZoneTask.invokeTask (zone.js:495)
at ZoneTask.invoke (zone.js:484)
at timer (zone.js:2053)
我可能在配置中遗漏了一些东西,但我无法弄明白。
我已经尝试过的:
我查看了示例应用程序 (https://github.com/ui-router/sample-app-angular-hybrid) 并尝试构建尽可能相似的应用程序。但他们使用的是 UpgradeModule 而不是降级 - 我不知道这是否会改变路由器的任何内容。
我试过了
- 将状态配置添加到 UIRouterUpgradeModule.forChild() 和 UIRouterModule.forChild()
- 根据https://github.com/ui-router/sample-app-angular-hybrid/blob/master/app/angularModule.ts#L10
创建了一个"future state"
- 声明账户状态的不同方式
- 定义帐户组件本身的不同方法
错误始终如一,因此我认为我只是在配置中遗漏了一些部分。
如果我的描述没有帮助,我会尝试设置一个 jsfiddle 或类似的东西
更新 1:
好的,我从 Angular 1 State Provider 中删除了帐户状态的状态声明,而是只在 UIRouterModule 中注册它。现在至少错误消失了,但是状态根本没有加载(尝试访问它时,重定向到默认状态)
好的,我终于设法解决了这个问题,多亏了另一篇文章的提示 ()
在这里再次引用它:
The Angular bootstrap module needed a parameter of type "UIRouter" in the constructor, otherwise it would not bootstrap its states:
export class AppModule {
constructor(private router: UIRouter) {
// "router" needed in constructor to bootstrap angular states
}
您还需要导入 UpgradeModule 和 UIRouterUpgradeModule。所以整个 app.module.ts 看起来像这样:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ServiceBootstrapComponent } from '../../service-bootstrap';
import { AccountNg2Component } from '../../app/pages/account/account.ng2.component';
import { UIRouterUpgradeModule } from '@uirouter/angular-hybrid';
import { AccountState } from '../../app/pages/account/account.states';
import { CommonModule } from '@angular/common';
import { UIRouter, UIRouterModule } from '@uirouter/angular';
import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({
imports: [
CommonModule,
BrowserModule,
UpgradeModule,
UIRouterUpgradeModule,
UIRouterModule.forChild({states: [AccountState]}),
],
declarations: [
ServiceBootstrapComponent,
AccountNg2Component,
],
providers: [
],
entryComponents: [
ServiceBootstrapComponent,
],
})
class AppModule {
constructor(private router: UIRouter) {}
public ngDoBootstrap(): void {}
}
export { AppModule };
首先对项目和一般设置做一些简短的介绍。
它是一个 Angular/Angular JS 应用程序。我几周前集成了 Angular。与许多使用 UpgradeModule 的不同教程相比,我实际上不得不使用 downgradeModule - 项目非常大,UpgradeModule 导致了很多性能问题。
有一个总体父状态(称为应用程序),我希望 Angular 组件成为它的子组件。根据文档,这应该是可能的 (https://github.com/ui-router/angular-hybrid#limitations)
Limitations: We currently support routing either Angular (2+) or AngularJS (1.x) components into an AngularJS (1.x) ui-view. However, we do not support routing AngularJS (1.x) components into an Angular (2+) ui-view.
If you create an Angular (2+) ui-view, then any nested ui-view must also be Angular (2+).
Because of this, apps should be migrated starting from leaf states/views and work up towards the root state/view.
一般设置如下所示(简化):
app.module.ng1.ts
import { AppModule } from './app.module';
const bootstrapFn: any = (extraProviders: Array<StaticProvider>): any => {
return platformBrowserDynamic(extraProviders).bootstrapModule(AppModule);
};
const downgradedModule: any = downgradeModule(bootstrapFn);
const appModule: angular.IModule = angular
.module('app', [
downgradedModule,
// other project modules
]);
app.module.ts
@NgModule({
imports: [
BrowserModule,
UIRouterUpgradeModule.forChild(),
],
declarations: [
AccountNg2Component,
],
providers: [
],
entryComponents: [
AccountNg2Component,
],
})
class AppModule {
public ngDoBootstrap(): void {}
}
export { AppModule };
TheAccountNg2Component 是我真正想去的那个。 account.component.ts
@Component({
selector: 'account',
template,
})
class AccountNg2Component {
@Input() public user: any;
constructor() {}
}
export { AccountNg2Component };
有一个父应用程序状态,我希望 AccountNg2Component 成为它的子级。状态配置如下所示:
$stateProvider
.state({
parent: 'app',
name: 'account',
url: '/account',
component: AccountNg2Component,
});
无论我尝试什么,都会导致以下两个错误:
Transition Rejection($id: 0 type: 6, message: The transition errored, detail: TypeError: Cannot read property 'when' of undefined)
TypeError: Cannot read property 'when' of undefined
at Ng2ViewConfig.load (views.js:47)
at eval (views.js:19)
at Array.map (<anonymous>)
at loadEnteringViews (views.js:19)
at invokeCallback (transitionHook.js:104)
at TransitionHook.invokeHook (transitionHook.js:116)
at eval (transitionHook.js:58)
at processQueue (angular.js:17169)
at eval (angular.js:17217)
at Scope.$digest (angular.js:18352)
at Scope.$apply (angular.js:18649)
at eval (angular.js:18952)
at completeOutstandingRequest (angular.js:6428)
at eval (angular.js:6707)
at ZoneDelegate.invokeTask (zone.js:420)
at Object.onInvokeTask (core.js:4961)
at ZoneDelegate.invokeTask (zone.js:419)
at Zone.runTask (zone.js:187)
at ZoneTask.invokeTask (zone.js:495)
at ZoneTask.invoke (zone.js:484)
at timer (zone.js:2053)
我可能在配置中遗漏了一些东西,但我无法弄明白。
我已经尝试过的:
我查看了示例应用程序 (https://github.com/ui-router/sample-app-angular-hybrid) 并尝试构建尽可能相似的应用程序。但他们使用的是 UpgradeModule 而不是降级 - 我不知道这是否会改变路由器的任何内容。
我试过了
- 将状态配置添加到 UIRouterUpgradeModule.forChild() 和 UIRouterModule.forChild()
- 根据https://github.com/ui-router/sample-app-angular-hybrid/blob/master/app/angularModule.ts#L10 创建了一个"future state"
- 声明账户状态的不同方式
- 定义帐户组件本身的不同方法
错误始终如一,因此我认为我只是在配置中遗漏了一些部分。
如果我的描述没有帮助,我会尝试设置一个 jsfiddle 或类似的东西
更新 1: 好的,我从 Angular 1 State Provider 中删除了帐户状态的状态声明,而是只在 UIRouterModule 中注册它。现在至少错误消失了,但是状态根本没有加载(尝试访问它时,重定向到默认状态)
好的,我终于设法解决了这个问题,多亏了另一篇文章的提示 ()
在这里再次引用它:
The Angular bootstrap module needed a parameter of type "UIRouter" in the constructor, otherwise it would not bootstrap its states:
export class AppModule {
constructor(private router: UIRouter) {
// "router" needed in constructor to bootstrap angular states
}
您还需要导入 UpgradeModule 和 UIRouterUpgradeModule。所以整个 app.module.ts 看起来像这样:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ServiceBootstrapComponent } from '../../service-bootstrap';
import { AccountNg2Component } from '../../app/pages/account/account.ng2.component';
import { UIRouterUpgradeModule } from '@uirouter/angular-hybrid';
import { AccountState } from '../../app/pages/account/account.states';
import { CommonModule } from '@angular/common';
import { UIRouter, UIRouterModule } from '@uirouter/angular';
import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({
imports: [
CommonModule,
BrowserModule,
UpgradeModule,
UIRouterUpgradeModule,
UIRouterModule.forChild({states: [AccountState]}),
],
declarations: [
ServiceBootstrapComponent,
AccountNg2Component,
],
providers: [
],
entryComponents: [
ServiceBootstrapComponent,
],
})
class AppModule {
constructor(private router: UIRouter) {}
public ngDoBootstrap(): void {}
}
export { AppModule };