【Angular】Component로 인젝션하는 Service를 전환할 수 있도록 해 본다

16204 단어 Angular
Angular를 만져서 같은 구성 요소로 서비스를 전환하고 싶을 때가 있습니까?
일반 유저용과 관리자용으로 화면은 함께하지만, 내용은 바꾸고 싶다든가.

서비스에 isAdmin 라든지 갖게 버립니다?
여러가지 함수로 if(isAdmin)
사실 서비스를 전환할 수 있습니다.

Angular 프로젝트 만들기


ng new service-test --routing

화면 추가



구성 요소 추가


  • 서비스에서 데이터를 검색하고 표시하도록합니다.

    src/app/page1/page1.component.ts
    import { Component } from '@angular/core';
    import { Page1Service } from './page1.service';
    
    @Component({
        selector: 'app-page1',
        template: `
            <h1>type: {{type}}</h1>
            <p>{{data}}</p>
        `,
    })
    export class Page1Component {
        constructor(private service: Page1Service) { }
    
        get type() { return this.service.type; }
        get data() { return this.service.getData(); }
    }
    

    서비스 추가


  • 일반 사용자를 위한 서비스 만들기

  • src/app/page1/page1.service.ts
    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class Page1Service {
        type = 'general';
    
        getData() {
            return 'これは一般ユーザー向けです';
        }
    }
    
  • 그런 다음 관리자 서비스를 만듭니다.
  • Page1Service 를 상속해 작성합니다 (상속하지 않아도 변수명이나 메소드명이 일치하면 문제 없다고 생각합니다)
  • abstract 클래스 만드는 것이 가장 안전하다고 생각합니다.


  • src/app/page1/page1-for-admin.service.ts
    import { Injectable } from '@angular/core';
    import { Page1Service } from './page1.service';
    
    @Injectable()
    export class Page1ForAdminService extends Page1Service {
        type = 'admin';
    
        getData() {
            return 'これは管理者ユーザー向けです';
        }
    }
    

    모듈 정의



    여기가 이번 간입니다! ! !
  • providers에서 useFactory를 사용하여 지정된 서비스를 다른 서비스로 교체
  • 이렇게하면 Component로 주입하는 서비스가 변경됩니다.


  • src/app/page1/page1.module.ts
    import { NgModule } from '@angular/core';
    import { Page1Component } from './page1.component';
    import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
    import { Page1Service } from './page1.service';
    import { Page1ForAdminService } from './page1-for-admin.service';
    import { Page1RoutingModule } from './page1-routing.module';
    
    @NgModule({
        declarations: [Page1Component],
        imports: [Page1RoutingModule],
        providers: [
            {
                // 置換対象のサービス
                provide: Page1Service,
                // 置換
                useFactory: (route: ActivatedRoute) => {
                    const getData = (snapshot: ActivatedRouteSnapshot) => snapshot.firstChild ? getData(snapshot.firstChild) : snapshot.data;
                    const isAdmin = getData(route.snapshot)?.isAdmin;
                    if (isAdmin) {
                        return new Page1ForAdminService();
                    }
                    return new Page1Service();
                },
                // useFactoryでインジェクションするサービス
                deps: [ActivatedRoute],
            }
        ]
    })
    export class Page1Module { }
    

    isAdmin은 후술하는 라우팅 파일로 설정하는 data내로부터 취득합니다

    라우팅 설정


  • Page1Module 내의 라우팅을 정의합니다

  • src/app/page1/page1-routing.module.ts
    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    import { Page1Component } from './page1.component';
    
    const routes: Routes = [
        // 一般ユーザー向け
        { path: '', component: Page1Component },
        // 管理者向け
        { path: 'admin', component: Page1Component, data: { isAdmin: true } },
    ];
    
    @NgModule({
        imports: [RouterModule.forChild(routes)],
        exports: [RouterModule]
    })
    export class Page1RoutingModule { }
    

    ⇒관리자를 위한 분은 data에 isAdmin을 설정합니다
  • /page1 액세스 할 때 Page1Module을 지연로드합니다.

    src/app/app-routing.module.ts
    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    
    const routes: Routes = [
      { path: 'page1', loadChildren: () => import('./page1/page1.module').then(m => m.Page1Module) },
    ];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
    

    동작 확인



  • http://localhost:4200/page1으로 이동



  • http://localhost:4200/page1/admin으로 이동



  • 마지막으로



    이런 식으로 간단? 에 컴포넌트를 공통화하면서 서비스만 교체할 수 있습니다.
    이렇게 하면 권한별로 if문이 늘어나거나 빗나가지 않기 때문에 비교적 서비스가 간단해집니다.

    파일수는 늘어나 Module이 복잡해진다는 단점도 있으므로, 사용점의 판별은 필요하네요.

    참고



    공장 공급자: useFactory

    좋은 웹페이지 즐겨찾기