评论

收藏

[JavaScript] 详解Angular依赖注入

开发技术 开发技术 发布于:2021-06-28 16:15 | 阅读数:446 | 评论:0

概述
  依赖注入:设计模式
  依赖:程序里需要的某种类型的对象。
  依赖注入框架:工程化的框架
DSC0000.jpg

  注入器Injector:用它的API创建依赖的实例
  Provider:怎样创建?(构造函数,工程函数)
  Object:组件,模块需要的依赖
  依赖性注入进阶=>Angular中依赖注入框架提供父子层次注入型依赖
一、依赖注入
class Id {
  static getInstance(type: string): Id {
  return new Id();
  }
}
class Address {
  constructor(provice, city, district, street) {}
}
class Person {
  id: Id;
  address: Address;
  constructor() {
  this.id = Id.getInstance("idcard");
  this.address = new Address("北京", "背景", "朝阳区", "xx街道");
  }
}
  问题:Person需要清楚的知道Address和Id的实现细节。
  ID和Address重构后,Person需要知道怎么重构。
  项目规模扩大后,集成容易出问题。
class Id {
  static getInstance(type: string): Id {
  return new Id();
  }
}
class Address {
  constructor(provice, city, district, street) {}
}
class Person {
  id: Id;
  address: Address;
  constructor(id: Id, address: Address) {
  this.id = id;
  this.address = address;
  }
}
main(){
  //把构造依赖对象,推到上一级,推调用的地方
  const id = Id.getInstance("idcard");
  const address = new Address("北京", "背景", "朝阳区", "xx街道");
  const person = new Person(id , address);
}
  Person已经不知道Id和Address的细节了。
  这是最简单的依赖注入。
  问题是在main里还是需要知道细节。
  思路:一级一级往上推,一直推到入口函数,入口函数来处理所有对象的构造。构造出来后提供给所有依赖的子模块的子类。
  问题:入口函数很难维护。所以需要一个依赖注入框架帮助完成。
二、Angular的依赖注入框架
  从v5开始,因为速度慢,引入大量代码已弃用,改为Injector.create。
  ReflectiveInjector :用于实例化对象和解析依赖关系。import { Component ,ReflectiveInjector } from "@angular/core";resolveAndCreate接收一个provider数组,provider告诉injector应该怎样去构造这个对象。
constructor() {
  //接收一个provider数组
  const injector = ReflectiveInjector.resolveAndCreate([
    {
    provide: Person, useClass:Person
    },
    {
    provide: Address, useFactory: ()=>{
      if(environment.production){
      return new Address("北京", "背景", "朝阳区", "xx街道xx号");
      }else{
      return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
      }
    }
    },
    {
    provide: Id, useFactory:()=>{
      return Id.getInstance('idcard');
    }
    }
  ]);
  }
  Injector:
  injector相当于main函数,可以拿到所有依赖池子里的东西。
import { Component ,ReflectiveInjector, Inject} from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";
import { Identifiers } from "@angular/compiler";
import { stagger } from "@angular/animations";
import { environment } from 'src/environments/environment';
@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent {
  constructor(private oc: OverlayContainer) {
  //接收一个provider数组
  const injector = ReflectiveInjector.resolveAndCreate([
    {
    provide: Person, useClass:Person
    },
    {
    provide: Address, useFactory: ()=>{
      if(environment.production){
      return new Address("北京", "背景", "朝阳区", "xx街道xx号");
      }else{
      return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
      }
    }
    },
    {
    provide: Id, useFactory:()=>{
      return Id.getInstance('idcard');
    }
    }
  ]);
  const person = injector.get(Person);
  console.log(JSON.stringify(person));
  }
}
class Id {
  static getInstance(type: string): Id {
  return new Id();
  }
}
class Address {
  provice:string;
  city:string;
  district:string;
  street:string;
  constructor(provice, city, district, street) {
  this.provice=provice;
  this.city=city;
  this.district=district;
  this.street=street;
  }
}
class Person {
  id: Id;
  address: Address;
  constructor(@Inject(Id) id, @Inject(Address )address) {
  this.id = id;
  this.address = address;
  }
}
  可以看到控制台打印出person信息。
DSC0001.jpg

  简写:
// {
    //   provide: Person, useClass:Person
    // },
    Person, //简写为Person
  在Angular框架中,框架做了很多事,在provider数组中注册的东西会自动注册到池子中。
@NgModule({
  imports: [HttpClientModule, SharedModule, AppRoutingModule, BrowserAnimationsModule],
  declarations: [components],
  exports: [components, AppRoutingModule, BrowserAnimationsModule],
  providers:[
  {provide:'BASE_CONFIG',useValue:'http://localhost:3000'}
  ]
})
constructor( @Inject('BASE_CONFIG') config) {
  console.log(config);  //控制台打印出http://localhost:3000
  }
  Angular默认都是单例,如果想要每次注入都是一个新的实例。有两种方法。
  一,return的时候return一个方法而不是对象。
{
  provide: Address, useFactory: ()=>{
    return ()=>{
      if(environment.production){
        return new Address("北京", "背景", "朝阳区", "xx街道xx号");
      }else{
        return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
      }
    }
  }
},
  二、利用父子Injector。
constructor(private oc: OverlayContainer) {
  //接收一个provider数组
  const injector = ReflectiveInjector.resolveAndCreate([
    Person,
    {
    provide: Address, useFactory: ()=>{
      if(environment.production){
      return new Address("北京", "背景", "朝阳区", "xx街道xx号");
      }else{
      return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
      }
    }
    },
    {
    provide: Id, useFactory:()=>{
      return Id.getInstance('idcard');
    }
    }
  ]);
  const childInjector = injector.resolveAndCreateChild([Person]);
  const person = injector.get(Person);
  console.log(JSON.stringify(person));
  const personFromChild = childInjector.get(Person);
  console.log(person===personFromChild);  //false
  }
  子注入器当中没有找到依赖的时候会去父注入器中找
  以上就是详解Angular依赖注入的详细内容,更多关于Angular的资料请关注脚本之家其它相关文章!

关注下面的标签,发现更多相似文章