我该如何解决此 Angular 7 "Circular dependency detected" 警告
How do I resolve this Angular 7 "Circular dependency detected" warning
在我的 Angular 7 项目中,我想要一个文件 "pages.ts",我可以在其中导出我的应用程序将拥有的路由。这些由 "app-routing.ts" 导入以供 RouterModule 使用,也由 "pages.service.ts" 导入,我想在其中管理这些路由的数据。现在,在我的组件之一 "test-one.component.ts" 中,我想使用该服务 "pages.service.ts" 这样我就可以通过路径或标题获取例如路线的数据。一切正常,但出现此警告。
WARNING in Circular dependency detected:
src/app/pages/test-one/test-one.component.ts -> src/app/core/services/pages.service.ts -> src/app/core/constants/pages.ts -> src/app/pages/test-one/test-one.component.ts
"pages.ts"
import { Page } from '../../core/models/page.model';
import { LoginComponent } from '../../pages/login/login.component';
import { SignupComponent } from '../../pages/signup/signup.component';
export const routePages: Page[] = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
component: LoginComponent,
canActivate: [],
data: {
title: 'Login',
description: '',
keywords: '',
icon: 'fingerprint',
hasBreadcrumb: true
},
pathMatch: 'full'
},
{
path: 'sign-up',
component: SignupComponent,
canActivate: [],
data: {
title: 'Sign up',
description: '',
keywords: '',
hasBreadcrumb: true
},
pathMatch: 'full'
}
];
"app-routing.module.ts"
import { routePages } from './core/constants/pages';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [RouterModule.forRoot(routePages, { scrollPositionRestoration: 'enabled' })],
exports: [RouterModule]
})
export class AppRoutingModule { }
"pages.service.ts"
import { routePages } from './../constants/pages';
import { Page, PageData } from './../models/page.model';
import { Router } from '@angular/router';
import { Injectable, EventEmitter } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PagesService {
pages = routePages;
private pagesChanged: EventEmitter<Page[]> = new EventEmitter<Page[]>();
constructor(private location: Location, private router: Router) {
this.setPagesFullPath();
console.log(this.pages);
}
.
.
.
}
"test-one.component.ts"
import { Page, PageData } from './../../core/models/page.model';
import { PagesService } from './../../core/services/pages.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-test-one',
templateUrl: './test-one.component.html',
styleUrls: ['./test-one.component.scss']
})
export class TestOneComponent implements OnInit {
testATwoPage: Page;
constructor(private pagesService: PagesService) {
}
ngOnInit() {
this.testATwoPage = this.pagesService.getPageByTitle('Test A two');
}
}
我很想知道如何在不放弃任何功能的情况下解决这种循环依赖。
提前致谢!
我不知道 PageService 的目的是什么,但我认为那是错误的。要访问路由器的数据,您应该使用 Router 事件或 ActivatedRoute,然后执行您必须执行的任何操作。例如,在这段代码中,我从路线中获取信息以在面包屑中使用:
this.router.events
.pipe(
filter(event => event instanceof NavigationEnd),
map(() => {
return this.getFirstChild(this.route.firstChild);
})
)
.subscribe(child => {
const title = child.snapshot.data['title'];
const previous = child.snapshot.data['previous'];
const parentUrl = child?.snapshot.parent?.url;
...
})
没有一种直接的解决方法。不过,我了解您的用例,并且有点支持它。你不应该在你的组件中有这种逻辑。它应该在服务中完成。你是对的。我不完全确定重用 Routes
导出是最好的主意。感觉你还是用Router.config
属性比较好。其中应包含整个路由配置:
@Injectable({
providedIn: 'root'
})
export class PagesService {
readonly pages: Routes = this.router.config;
private pagesChanged: EventEmitter<Page[]> = new EventEmitter<Page[]>();
constructor(private location: Location, private router: Router) {
this.setPagesFullPath();
console.log(this.pages);
}
}
如果这样做,无论出于何种原因都不起作用。摆脱循环依赖的方法是拆分成多个文件。主要问题是您的 routePages
。您可以将其转换为两个文件。一个是 pages.ts:
pages.ts
export enum PageRoute {
Login: 'login',
SignUp: 'sign-up'
}
export interface PageData {
title: string;
description: string;
keywords: string;
icon?: string;
hasBreadcrumb: boolean;
}
export const PageRouteData: Record<PageRoute, PageData> {
[AppPage.Login]: {
title: 'Login',
description: '',
keywords: '',
icon: 'fingerprint',
hasBreadcrumb: true
},
[AppPage.SignUp]: {
title: 'Sign up',
description: '',
keywords: '',
hasBreadcrumb: true
}
}
还有另一个文件,它实际上包含由路由器消化的路由:
app.routes.ts
export const routePages: Page[] = [
{
path: '',
redirectTo: PageRoute.Login,
pathMatch: 'full'
},
{
path: PageRoute.Login,
component: LoginComponent,
data: PageRouteData[PageRoute.Login]
},
{
path: PageRoute.SignUp,
component: SignupComponent,
data: PageRouteData[PageRoute.SignUp]
}
];
旁注:仅当您有 redirectTo
时才需要 pathMatch
这样你就不需要在你的 PagesService
中导入 app.routes
并且循环依赖得到解决
在我的 Angular 7 项目中,我想要一个文件 "pages.ts",我可以在其中导出我的应用程序将拥有的路由。这些由 "app-routing.ts" 导入以供 RouterModule 使用,也由 "pages.service.ts" 导入,我想在其中管理这些路由的数据。现在,在我的组件之一 "test-one.component.ts" 中,我想使用该服务 "pages.service.ts" 这样我就可以通过路径或标题获取例如路线的数据。一切正常,但出现此警告。
WARNING in Circular dependency detected: src/app/pages/test-one/test-one.component.ts -> src/app/core/services/pages.service.ts -> src/app/core/constants/pages.ts -> src/app/pages/test-one/test-one.component.ts
"pages.ts"
import { Page } from '../../core/models/page.model';
import { LoginComponent } from '../../pages/login/login.component';
import { SignupComponent } from '../../pages/signup/signup.component';
export const routePages: Page[] = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'login',
component: LoginComponent,
canActivate: [],
data: {
title: 'Login',
description: '',
keywords: '',
icon: 'fingerprint',
hasBreadcrumb: true
},
pathMatch: 'full'
},
{
path: 'sign-up',
component: SignupComponent,
canActivate: [],
data: {
title: 'Sign up',
description: '',
keywords: '',
hasBreadcrumb: true
},
pathMatch: 'full'
}
];
"app-routing.module.ts"
import { routePages } from './core/constants/pages';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [RouterModule.forRoot(routePages, { scrollPositionRestoration: 'enabled' })],
exports: [RouterModule]
})
export class AppRoutingModule { }
"pages.service.ts"
import { routePages } from './../constants/pages';
import { Page, PageData } from './../models/page.model';
import { Router } from '@angular/router';
import { Injectable, EventEmitter } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PagesService {
pages = routePages;
private pagesChanged: EventEmitter<Page[]> = new EventEmitter<Page[]>();
constructor(private location: Location, private router: Router) {
this.setPagesFullPath();
console.log(this.pages);
}
.
.
.
}
"test-one.component.ts"
import { Page, PageData } from './../../core/models/page.model';
import { PagesService } from './../../core/services/pages.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-test-one',
templateUrl: './test-one.component.html',
styleUrls: ['./test-one.component.scss']
})
export class TestOneComponent implements OnInit {
testATwoPage: Page;
constructor(private pagesService: PagesService) {
}
ngOnInit() {
this.testATwoPage = this.pagesService.getPageByTitle('Test A two');
}
}
我很想知道如何在不放弃任何功能的情况下解决这种循环依赖。
提前致谢!
我不知道 PageService 的目的是什么,但我认为那是错误的。要访问路由器的数据,您应该使用 Router 事件或 ActivatedRoute,然后执行您必须执行的任何操作。例如,在这段代码中,我从路线中获取信息以在面包屑中使用:
this.router.events
.pipe(
filter(event => event instanceof NavigationEnd),
map(() => {
return this.getFirstChild(this.route.firstChild);
})
)
.subscribe(child => {
const title = child.snapshot.data['title'];
const previous = child.snapshot.data['previous'];
const parentUrl = child?.snapshot.parent?.url;
...
})
没有一种直接的解决方法。不过,我了解您的用例,并且有点支持它。你不应该在你的组件中有这种逻辑。它应该在服务中完成。你是对的。我不完全确定重用 Routes
导出是最好的主意。感觉你还是用Router.config
属性比较好。其中应包含整个路由配置:
@Injectable({
providedIn: 'root'
})
export class PagesService {
readonly pages: Routes = this.router.config;
private pagesChanged: EventEmitter<Page[]> = new EventEmitter<Page[]>();
constructor(private location: Location, private router: Router) {
this.setPagesFullPath();
console.log(this.pages);
}
}
如果这样做,无论出于何种原因都不起作用。摆脱循环依赖的方法是拆分成多个文件。主要问题是您的 routePages
。您可以将其转换为两个文件。一个是 pages.ts:
pages.ts
export enum PageRoute {
Login: 'login',
SignUp: 'sign-up'
}
export interface PageData {
title: string;
description: string;
keywords: string;
icon?: string;
hasBreadcrumb: boolean;
}
export const PageRouteData: Record<PageRoute, PageData> {
[AppPage.Login]: {
title: 'Login',
description: '',
keywords: '',
icon: 'fingerprint',
hasBreadcrumb: true
},
[AppPage.SignUp]: {
title: 'Sign up',
description: '',
keywords: '',
hasBreadcrumb: true
}
}
还有另一个文件,它实际上包含由路由器消化的路由:
app.routes.ts
export const routePages: Page[] = [
{
path: '',
redirectTo: PageRoute.Login,
pathMatch: 'full'
},
{
path: PageRoute.Login,
component: LoginComponent,
data: PageRouteData[PageRoute.Login]
},
{
path: PageRoute.SignUp,
component: SignupComponent,
data: PageRouteData[PageRoute.SignUp]
}
];
旁注:仅当您有 redirectTo
pathMatch
这样你就不需要在你的 PagesService
中导入 app.routes
并且循环依赖得到解决