我创建了一个Angular Component Library,并通过NPM(通过Nexus)将其分发到几个类似的项目。它包含一个PageComponent
,后者又包含一个FooterComponent
和一个NavbarComponent
。在NavbarComponent
中存在一个按钮,该按钮触发logout
功能。该功能将通过相应项目的PageService
提供。为此,我在Angular Component库中创建了一个AbstractPageService
(PageService
扩展了AbstractPageService
)。
首先,我通过EventEmitter
解决了这个问题。但是由于我必须为每个新页面提供一个logout
函数,所以我想通过每个项目一个服务来解决这个问题。我使用Angular Component Library的PageService
方法传递了forRoot()
(项目)。
一切正常,但是想知道是否有更好的解决方案,或者该解决方案是否值得推荐?
我是Angular的新手,但我还是有点不安全。我希望你明白我想要的。我的英语不是最好的。 :D
我对此有以下解决方案:
组件库-components.module.ts
import {ModuleWithProviders, NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {RouterModule} from '@angular/router';
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
import {NavbarComponent} from './layout/navbar/navbar.component';
import {PageComponent} from './layout/page/page.component';
import {PageHeaderComponent} from './components/page-header/page-header.component';
// ... others ...
@NgModule({
imports: [
CommonModule,
RouterModule,
FontAwesomeModule
],
declarations: [
NavbarComponent,
PageComponent,
// ... others ...
],
exports: [
NavbarComponent,
PageComponent,
// ... others ...
]
})
export class ComponentsModule {
static forRoot(pageService): ModuleWithProviders {
return {
ngModule: ComponentsModule,
providers: [
{provide: 'PageService', useClass: pageService}
]
};
}
}
组件库-page.component.ts
import {Component, EventEmitter, HostBinding, Inject, Input, Output} from '@angular/core';
import {AbstractPageService} from '../../services/abstract-page.service';
@Component({
selector: 'dc-page',
templateUrl: './page.component.html',
styleUrls: ['./page.component.scss']
})
export class PageComponent {
@HostBinding('class') styleClass = 'd-flex flex-column';
@Input() customStyleClass = null;
@Input() showLogoutButton = true;
// @Output() logoutButtonClick: EventEmitter<any> = new EventEmitter();
constructor(@Inject('PageService') protected pageService: AbstractPageService) {
}
logout(): void {
this.pageService.logout();
}
}
组件库-abstract-page.service.ts
import {Injectable} from '@angular/core';
@Injectable()
export abstract class AbstractPageService {
abstract logout(): void;
}
这里是项目中的用途:
项目-app.module.ts
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {AppComponent} from './app.component';
import {RouterModule, Routes} from '@angular/router';
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
import {ComponentsModule} from 'components';
const appRoutes: Routes = [
{path: '', component: AppComponent},
// otherwise redirect to home
{path: '**', redirectTo: ''}
];
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
FontAwesomeModule,
RouterModule.forRoot(appRoutes),
ComponentsModule.forRoot(PageService),
],
providers: [
// {provide: 'PageService', useClass: PageService}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
项目-page.service.ts
import {Injectable} from '@angular/core';
import {AbstractPageService} from '../../../projects/components/src/lib/services/abstract-page.service';
@Injectable({
providedIn: 'root'
})
export class PageService extends AbstractPageService {
constructor() {
super();
}
logout() {
console.log('Ausloggen!');
}
}
答案 0 :(得分:6)
我使用了这种方法,但是遇到了一个问题:
PageService
与应用程序中的库中的string
不同。由于它是在多个模块(应用程序模块和库模块)中提供的,因此会创建一个新的每个模块的实例。
我最终要做的是通过应用程序模块中的// app.module.ts in the root application
providers: [
{
provide: 'PageService',
useClass: PageService
}
]
提供服务:
@Inject()
然后使用// anywhere in the root application where the service is needed
constructor(@Inject('PageService') private pageService: PageService) {}
export interface AbstractPageService {
logout(): void;
}
然后,在库中,我创建了一个简单的界面:
Inject()
然后,我可以简单地通过// anywhere in the library where the service is needed
constructor(@Inject('PageService') private pageService: AbstractPageService) {}
装饰器将服务注入到库中,然后使用该接口键入该服务(无需在根应用程序中实现该接口):
PageService
现在,根应用程序和都使用与根应用程序相同的AWSRequestSigningApacheInterceptor
的单例实例。
答案 1 :(得分:1)
重用单例
{ provide: 'currentCompanyService', useFactory: getCompanyServiceFactory, deps: [AppInitService]}
创建只返回注入实例的工厂。
export function getCompanyServiceFactory(appInitService: AppInitService): AppInitService {
return appInitService;
}
public CustomLibraryComponent {
private companyService: AppInitService;
constructor(@Inject('currentEnvironment') environment: any,
@Inject('currentCompanyService') companyService: AppInitService) {
this.environment = environment;
this.companyService = companyService;
}
}
答案 2 :(得分:0)
如Sunil Singh所说,解决方案是普通的抽象类(没有@Injectable
)。
export abstract class AbstractPageService {
abstract logout(): void;
}
答案 3 :(得分:0)
我认为应该有“ useValue”而不是“ useClass”。
export class ComponentsModule {
static forRoot(pageService): ModuleWithProviders {
return {
ngModule: ComponentsModule,
providers: [
{provide: 'PageService', useClass: pageService}
]
};
}
}