依赖注入

前端之家收集整理的这篇文章主要介绍了依赖注入前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

依赖注入(DependencyInJection 简称DI)依然在线竞拍为例子

控制反转:Inversionof Control 简称:IOC

Varproducr =new Product();

product依赖Product

依赖注入模式及使用的好处,angular如何实现依赖注入

注入器的层级关系

松耦合和可重用性,提高可测试性


实现依赖注入:

注入器:每个组件都有一个注入器,负责注入组件需要的对象

注入器:

constructor( private productService:ProductService) {...}

提供器:不同的写法

providers:[{provider:ProductService,useClass:ProductService}]

providers:[ProductService]//如果provideruseClass一样可以简写成这样

providers:[{provider:ProductService,useClass:AnotherProductService}]

解释:联动注入器,其实真正的实例化是AnotherProductService,原因是注入器中的ProductService,根据提供器中的ProductService来匹配要注入的对象和提供器的,然后根据useClass提供什么类,就实例化什么类!(简洁一句话就是:真正的注入的是useClass这个类)

provider:[{provide:ProductService,useFactory:()=>{...}}]

解释:就是通过工厂方法返回的实例,然后将返回的实例注入到注入器中

实例演示:

新建一个项目ngnew di

新建组件ng gcomponent product1

新建服务ng gservice shared/product

修改product.service.ts

import { Injectable } from '@angular/core';

@Injectable()

export class ProductService {

constructor() { }

//添加的地方--------------------------------

getProduct():Product{

return new Product(0,"iPhone",5899,"最新版")

}

//--------------------------

}

//添加到类

export class Product{

constructor(

public id:number,

public title:string,

public price:number,

public desc:string

){

}

}

app.module.ts中引入

providers: [ProductService],

修改product1的控制器product1.component.ts

import { Component,OnInit } from '@angular/core';

import { Product,ProductService } from '../shared/product.service';

@Component({

selector: 'app-product1',

templateUrl: './product1.component.html',

styleUrls: ['./product1.component.css']

})

export class Product1Component implements OnInit {

//声明一个变量,然后在构造函数中通过依赖注入声明需要的服务

product:Product;

constructor(private productService:ProductService) { }

ngOnInit() {

this.product=this.productService.getProduct();

}

}

图解:红框中的代码添加代码


修改product1.component.html

<div>

<h1>商品详情</h1>

<h2>名称{{product.title}}</h2>

<h2>价格:{{product.price}}</h2>

<h2>描述:{{product.desc}}</h2>

</div>

修改app.component.html

<div>

<div>

<h1>基本的依赖注入</h1>

</div>

<div>

<app-product1></app-product1>

</div>

</div>

运行程序:结果截图


新建组件ng g component product2

新建服务ng g service shared/anotherProduct

修改another-product.service.ts控制器

import { Injectable } from '@angular/core';

import { ProductService,Product } from './product.service';

@Injectable()

//实现productService接口

export class AnotherProductService implements ProductService{

getProduct(): Product {

return new Product(1,"三星手机",4899,"最新版手机");

}

constructor() { }

}

修改product2.component.ts控制器

import { Component,ProductService } from '../shared/product.service';

import { AnotherProductService} from '../shared/another-product.service';

@Component({

selector: 'app-product2',

templateUrl: './product2.component.html',

styleUrls: ['./product2.component.css'],

//添加一个注入器,让他实例化AnotherProductService类,是another-product.service.ts中的一个类

providers:[{

provide:ProductService,useClass:AnotherProductService

}]

})

export class Product2Component implements OnInit {

product:Product;

constructor(private productService:ProductService) { }

ngOnInit() {

this.product=this.productService.getProduct();

}

}

修改product2.component.html

<div>

<h1>商品详情</h1>

<h2>名称{{product.title}}</h2>

<h2>价格:{{product.price}}</h2>

<h2>描述:{{product.desc}}</h2>

</div>

修改app.component.html

<div>

<div>

<h1>基本的依赖注入</h1>

</div>

<div>

<app-product1></app-product1>

<app-product2></app-product2>

</div>

</div>

总结注入器的作用域规则

第一点:一个提供器声明在模块时,是对所有组件可见的,所有组件都是可以注入的

第二点:声明在组件内的时候,只对组件和子组件可见其他组件不能注入

第三点:声明在模块的提供器和声明在组件内的提供器时,组件内的可以覆盖模块中的 提供器

第四点:我们应该优先把提供器声明在模块中,只有需要对其他组件不可见时才声明在组件中,但这种情况是非常罕见的。

-------------------------------------------------

product.service.ts控制器

@Injectable()

export class ProductService {

constructor() { }

getProduct():Product{

return new Product(0,"最新版")

}

}


图中的productService可以注入别的服务(通过构造函数将其他服务注入到本服务中),本服务能不能注入到别的服务是看本服务有没有在providers属性中声明决定的,

@Injectable()这个装饰器只要有@Injectable()服务就能将别的服务注入进来

@Injectable()

export classProductService {

@Injectable()这个装饰器的意思是,其他服务也可以注入到这个服务中,建议给每个服务都添加这个装饰器。

问题:为啥我组件上没有声明这个装饰器也可以注入服务,因为@Component装饰器是@Injectable()装饰器的子类。

而这个服务是否可以注入到其他服务中,是根据他是否声明在app.module.ts中的providers属性中决定的。

import { BrowserModule } from '@angular/platform-browser';

import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

import { Product1Component } from './product1/product1.component';

import { ProductService } from './shared/product.service';

import { Product2Component } from './product2/product2.component';

@NgModule({

declarations: [

AppComponent,

Product1Component,

Product2Component

],

imports: [

BrowserModule

],

providers: [ProductService],

bootstrap: [AppComponent]

})

export class AppModule { }


服务之间如何互相注入

新建服务ng g service shared/logger

import { Injectable } from '@angular/core';

@Injectable()

export class LoggerService {

constructor() { }

log(message:string){

console.log(message);

}

}

修改 app.module.ts

providers: [ProductService,LoggerService],

修改product.service.ts

import { Injectable } from '@angular/core';

import { LoggerService } from './logger.service';

@Injectable()

export class ProductService {

constructor(private logger:LoggerService) { }

getProduct():Product{

this.logger.log("getproduct方法调用");

return new Product(0,"最新版")

}

}

export class Product{

constructor(

public id:number,

public desc:string

){

}

}

运行结果:

重构Auction

1、编写ProductService 包含3方法getProducts(),getProduct(id)以及getCommentsForProduct(id);

2修改路由配置。在从商品列表进入商品详情时不在传输商品名称修改传输商品ID

3、注入ProductService并使用其服务。

添加一个服务:ng g service shared/product

修改product.service.ts

import { Injectable } from '@angular/core';

@Injectable()

export class ProductService {

//数组

private products:Product[]=[

new Product(1,"第一个商品",1.99,3.5,"我是学习Angular",["电子","物电"]),//ID 商品名称,价格,星级,商品描述,商品类别

new Product(2,"第二个商品",1.5,

new Product(3,"第三个商品",2.5,

new Product(4,"第四个商品",

new Product(5,"第五个商品",

new Product(6,"第六个商品",4.5,"物电"])

];

private@H_837_2403@ comments@H_837_2403@:Comment@H_837_2403@[]=[//商品评论的实体,包括商品评论的信息

new Comment(1,1,"201842317:14:08","张三",3,"东西很好"),

new Comment(2,"李四","东西挺好"),

new Comment(3,"王五","东西还行"),

new Comment(4,"赵柳","东西不错")

]

constructor() { }

//第一个方法,返回这个数组信息

getProducts():Product[]{

return this.products;

}

//根据商品的id,返回相应的商品

getProduct(id:number):Product {

return this.products.find((product)=>product.id==id);

}

//根据商品的id,返回所有的评论信息(filter:是过滤)

getCommentsForProdutId(id:number):Comment[]{

return this.comments.filter((comment:Comment)=>comment.productid==id);

}

}

export class Product{

constructor(

public id:number,

public rating:number,

public desc:string,

public categories:Array<string>

){}

}

//商品评论的类

export class Comment{

constructor(public id:number,

public productid:number,

public timestamp:string,

public user:string,

public content:string

){

}

}

解释:主要就是将数据移植到这里来,Product,就是一个实体

修改路由配置:修改app.module.ts(之前传的是商品的名称,现在传的是id,所以修改两处

{第一处:path:'product/:productId',component:ProductDetailComponent}中的prodTitle改成productId 第二处:providers: [ProductService]

//-------------------------------------------------------------------------

部分代码:如下

import { ProductService } from './shared/product.service';

const routeConfig:Routes=[

{path:'',component:HomeComponent},

{path:'product/:productId',component:ProductDetailComponent}

]

修改商品组件的模板上:product.component.html

<!--let product of products绑定后台的数据-->

<div *ngFor="let product ofproducts" class="col-md-4 col-sm-4 col-lg-4">

<div class="thumbnail">

<!-- <img src="http://placehold.it/320X150">-->

<img[src]="imgUrl"><!--属性绑定 -->

<div class="caption">

<h4class="pull-right">{{product.price}}</h4>

<h4><a [routerLink]="['/product',product.id]">{{product.title}}</a></h4>

<p>{{product.desc}}</p>

</div>

<div>

<app-stars [rating]="product.rating"></app-stars>

<!-- <app-stars>{{product.rating}}</app-stars>-->

</div>

</div>

</div>

商品详情的组件上,修改控制器:product-detail.component.ts

export class ProductDetailComponentimplementsOnInit {

product:Product;

comments:Comment[];

constructor(private routeInfo:ActivatedRoute,

private productService:ProductService) { }

ngOnInit() {

let productId:number=this.routeInfo.snapshot.params["productId"]

//this.productTitle=this.routeInfo.snapshot.params["prodTitle"]

}

}

注入productService并且使用其服务:修改app.module.ts

providers:@H_837_2403@ [ProductService@H_837_2403@],//把服务声明在模块的providers属性

然后在商品组件中构造函数中注入productService修改product.component.ts

constructor(private productService:ProductService) { }

详细代码

import { Component,OnInit } from '@angular/core';

import { ProductService,Product } from '../shared/product.service';

@Component({

selector: 'app-product',

templateUrl: './product.component.html',

styleUrls: ['./product.component.css']

})

export class ProductComponent implements OnInit {

private products:Product[];

private imgUrl='http://placehold.it/320X150';

constructor(private productService:ProductService) { }

ngOnInit() {//组件实例化的钩子

this.products=this.productService.getProducts();

}

}

然后接着在修改product-detail.component.ts

this.product=this.productService.getProduct(productId);

然后接着修改product-detail.component.html

<div class="thumbnail">

<img src="http://placehold.it/820X230">

<h4 class="pull-right">{{product.price}}</h4>

<h4>{{product.title}}</h4>

<p>{{product.desc}}</p>

<div>

<p class="pull-right">{{comments.length}}</p>

<p>

<app-stars [rating]="product.rating"></app-stars>

</p>

</div>

</div>

<div class="well">

<div class="row" *ngFor="let comment ofcomments">

<hr>

<div class="col-md-12">

<app-stars [rating]="comment.rating"></app-stars>

<span>{{comment.user}}</span>

<span>{{comment.timestamp}}</span>

<p></p>

<p>{{comment.content}}</p>

</div>

</div>

</div>

猜你在找的设计模式相关文章