美文网首页
16Angular依赖注入

16Angular依赖注入

作者: learninginto | 来源:发表于2020-12-28 11:53 被阅读0次
    • 什么是依赖注入?

    依赖注入(DI)是一种设计模式,也有相应的框架,比如InversifyJS

    在这里介绍Angular自己的DI框架,它会在实例化该类时向其提供该类所生命的依赖项

    带修饰符的参数

    在ts中,一个类的参数如果带上修饰符,那个参数就变成了类的实例属性

    class Mobile{
        constructor(readonly name:string = '小米'){}
        logName(){
            console.log(this.name)
        }
    }
    

    上面的name有修饰符,那么它就是Mobile类的实例属性,等同于:

    class Mobile{
        readony name:string
        constructor(){
            this.name = '小米'
        }
        logName(){
            console.log(this.name)
        }
    }
    

    实现过程

    • 创建服务
    ng g s hero
    

    被@Injectable装饰的类,就是一个可以被注入的类,也称为服务(为其他服务、组件、指令或管道提供服务)

    import {Injectable} from '@angular/core'
    import {HEROS} from './mock-heroes'
    @Injectable({
        providedIn:'root'
    })
    export class HeroService {
        constructor(){}
        getHeroes(){
            return HEROS;
        }
    }
    
    • 使用服务(例如:使用Renderer2操作DOM元素)

    在构造函数中直接声明,Angular框架帮我们完成注入(开箱即用),默认是单例模式(A、B模块同时注入时,得到的是同一个)

    import {Renderer2} from '@angular/core'
    constructor(private rd2:Renderer2)
    @ViewChildren('img') imgs:QueryList<ElementRef>
    
    ngAterViewInit():void{
        this.imgs.forEach(item=>{
          this.rd2.setStyle(item.nativeElement,'height','100px')
          //设置属性时为this.rd2.setProperty()
        })
    }
    
    • 提供服务的地方
    1. 在服务本身的@Injectable()的装饰器中
    2. 在NgModule的@NgModule()的装饰器中,providers数组,或import对应模块
    ngOnInit(){
        const injector = Injector.create({
            providers:[
                {
                    provide:Product,
                    //useClass:Product
                    useFactory:() => {
                        return new Product("xxx")
                    },
                    deps:[]
                    //如果还依赖其他的内容,需要在deps数组中提供
                },
                //在这里写也可以
                {
                    provide:PurchaseOrder,
                    useClass:PurchaseOrder,
                    deps:[Product]
                }
                //如果provide和useClass的名字相同,也可以这样 
                //PurchaseOrder
            ]
        })
    }
    
    1. 在组件的@Component()装饰器中
    @Component({
        selector:'',
        templateUrl:'',
        styleUrls:'[]',
        changeDetection:ChangeDetectionStragegy.OnPush,
        providers:[HeroService]
    })
    

    通常,在使用的时候不需要这么麻烦,只需要放在module.ts中的providers就可以

    替代类

    useClass和provide可以是不一样的类

    providers:[
        {provide:LoggerService, useClass:BetterLoggerService}
    ]
    
    值提供者

    对于很简单的值,没必要把它做成一个类,可用useValue提供简单的值

    providers:[{provide:Logger,useValue:'simpleValue'}]
    
    非类令牌

    上面的每个provide都是一个类,那么也可以用其它数据类型作为令牌

    providers:[{provide:'httpApi', useValue:'123.com'}]
    
    • 注入方式
    class AppComponent{
        constructor(@Inject('httpApi') readonly api){}
    }
    
    InjectionToken

    当知道要注入的是什么类型时,可以用InjectionToken

    interface AppConfig {
     apiEndpoint : string;
     title : string
    }
    

    无法用AppConfig作为令牌

    [
        {
            provide:AppConfig,
            useValue:{
                apiEndPoint:'api.heros.com',
                title:'Dependency Injection'
            }
        }
    ]
    

    但又想要限制值的类型,可以借助InjectionToken

    import { InjectionToken } from '@angular/core'
    //参数是该令牌的一个描述,可选择
    export const APP_CONFIG = new InjectionToken<AppConfig>('app.config')
    [
        {
            provide:APP_CONFIG,
            useValue:{
                apiEndPoint:'api.heros.com',
                title:'Dependency Injection'
            }
        }
    ]
    

    注入方式

    class AppComponent{
        constructor(@Inject(APP_CONFIG) config: Appconfig){
            this.title = config.title
        }
    }
    
    工厂提供者
    import { Injectable } from '@angular/core';
    import {UserService} from './user.service';
    import {LoggerService} from './logger.service';
    
    @Injectable()
    export class UserLoggerService extends LoggerService {
      constructor(private userService: UserService, extra: string) {
        super();
        console.log('UserLoggerService', extra);
      }
      log(message: string) {
        const name = this.userService.user.name;
        super.log(`Message to ${name}: ${message}`);
      }
    }
    
    {
      provide: UserLoggerService,
      useFactory(userServe: UserService) {
        return new UserLoggerService(userServe, 'factory msg');
      },
      deps: [UserService] // 依赖其它服务的话,要列在这里
    }
    

    相关文章

      网友评论

          本文标题:16Angular依赖注入

          本文链接:https://www.haomeiwen.com/subject/rzvznktx.html