您现在的位置是:首页 >其他 >由路由守卫引发的Angular DI inject思考网站首页其他

由路由守卫引发的Angular DI inject思考

无敌喜之郎 2024-06-04 12:00:02
简介由路由守卫引发的Angular DI inject思考

在我修改以前模块的时候,发现路由守卫中的CanActivate已经标记废弃了,现在官网中推荐的是一种模版代码更少的写法:

export const yourGuard: CanActivateFn = (
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
) => {
   // your  logic goes here
}

秉承及时更新代码的原则,我立即对该模块中的路由守卫代码进行了更改,但在修改时遇到了一个问题,即判断逻辑依赖于其他注入,这没有constructor你让我很难办啊 。于是我只好再探官网,发现可以使用 inject 来引用其他依赖项(例: const router = inject(Router) )。
那么这个inject是什么东东呢?

众所周知,在 Angular 中的组件/指令/管道中如果需要使用某个服务,必须通过构造函数参数注入才可使用。

import { Component } from '@angular/core';
import { Injectable } from '@angular/core';
​
@Injectable()
export class HeroService {
  constructor() {}
}
​
@Component({
  selector: 'app-inject',
  template: ``,
  standalone: true,
  providers: [HeroService],
})
export class InjectComponent {
  constructor(private heroService: HeroService) {}
}

如果创建的服务没有通过@Injectable注解进行依赖注入,那么就需要创建一个InjectionToken,此外还需要使用@Inject()注解来在构造函数中引用该依赖项

import { Component, Inject } from '@angular/core';
import { InjectionToken } from '@angular/core';export const InjectToken = new InjectionToken<InjectToken>(
  'Hero_Inject_Token'
);export class HeroService {
  constructor() {}
}
​
@Component({
  selector: 'app-inject',
  template: ``,
  standalone: true,
  providers: [
    {
      provide: InjectToken,
      useClass: HeroService,
    },
  ],
})
export class InjectComponent {
  constructor(
    @Inject(InjectToken) private heroService: HeroService
  ) {}
}

回顾完DI的基础知识,再来看一下官方是怎样解释的

inject可以在以下四种情况使用
在为 Provider 的 @ Injectable useFactory 的工厂函数中
在为 InjectionToken 指定的 factory 函数中。

export const NameToken = new InjectionToken<string>('NAME_TOKEN');
​
@Injectable()
export class HeroService {
  name = 'hero';
  constructor() {}
}
​
@Injectable()
export class SecretHeroService {
  name = 'secretHero';
  constructor() {}
}providers: [
  SecretHeroService,
  //在为  InjectionToken  指定的  factory  函数中
  {
    provide: NameToken,
    useFactory: () => {
      return inject(HeroService).name;
    },
  },
  //在为Provider的Injectable useFactory的工厂函数中
  {
    provide: HeroService,
    useFactory: () => {
      return inject(SecretHeroService);
    },
  },
],

由 DI 系统实例化的类的构造(通过 constructor ),例如 @ Injectable 或 @ Component 。

constructor() {
    const service = inject(HeroService);
    const heroName = service.name
}

在此类类的字段的初始化器中。

 name = inject(HeroService).name;

我们可以拿它干啥?

可以更轻松地在组件之间共享依赖项,并减少对父组件的依赖性。例如,在父组件中使用多个服务时,子组件可以使用 angular inject 注入这些服务,就可以不必手动注入每个服务。
可以让更加方便地在子组件中注入父组件中使用的服务,而不必关心父组件到底使用了哪些注入项。这样的设计可以提高代码的可重用性,使得子组件的实现更加独立,不会被父组件的变化所影响
未使用inject

@Injectable({  providedIn: 'root'})
export class childService extends ParentService {
  constructor(public http: HttpClient) {
    super(http);
  }
}
​
@Injectable({  providedIn: 'root'})
export class ParentService {
  constructor(public http: HttpClient) {}
}

使用inject

@Injectable({ providedIn: 'root' })
export class childService extends ParentService {
  constructor() {
    super();
  }
}
​
@Injectable({ providedIn: 'root' })
export class ParentService {
  http = inject(HttpClient);
  constructor() {}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。