新建路由配置
在app.module.ts中配置
....
import {RouterModule, Routes} from "@angular/router";
const routeConfig:Routes = [
{path:'',component:HomeComponent},
{path:'product/:prodTitle',component:ProductDetailComponent}
]
....
imports: [
BrowserModule,
RouterModule.forRoot(routeConfig)
],
依赖注入“自动处理对象的创建过程”
开始新的例子
1、新建Inject 项目
ng new Inject
2、新建product1组件
ng g component product1
3、新建服务
ng g service shared/product
1、在app.module.ts模块中提供器providers 定义ProductService对象
2、在productService中定义Product对象,在productService的控制的中构造方法中定义getProduct()方法用来返回实例化后的Product对象
3、在product1组件中定义product变量,类型为Product对象,用于模块渲染
4、在product1组件中的构造方法,注入ProductService对象
5、在product1组件的ngOnInit函数中给product变量赋值,通过调用ProductService的getProduct方法实现
6、模板中做变量调用
后附源码
4、新建product2组件
ng g component product2
5、新建anotherProduct 服务组件
ng g service shared/anotherProduct
案例解析 | anotherProductService中的代码实现
调用ProductService中的接口,复写实现getProduct()方法来返回Product对象的值
import { Injectable } from '@angular/core';
import {Product, ProductService} from "./product.service";
@Injectable()
export class AnotherProductService implements ProductService{
getProduct(): Product {
return new Product(1,'sumsung s7',4899,'新最新款三星手机');
}
constructor() { }
}
product2组件中通过定义providers提供器的useClass属性来调用AnotherProductService对象来实现数据的加载
import { Component, OnInit } from '@angular/core';
import {Product, ProductService} from "../shared/product.service";
import {AnotherProductService} from "../shared/another-product.service";
@Component({
selector: 'app-product2',
templateUrl: './product2.component.html',
styleUrls: ['./product2.component.css'],
providers:[{
provide:ProductService,useClass:AnotherProductService
}]
})
export class Product2Component implements OnInit {
product:Product;//需要一个变量用于模板渲染
constructor(private productService:ProductService) { }
ngOnInit() {
/* 组件生成的生命周期函数里面 给product变量赋值 */
this.product = this.productService.getProduct();
}
}
提供器的作用域
1、提供器providers声明在模块中时,对所有组件可见的,所有组件都可以注入它;
2、当提供器providers声明在组件中时,只对组件及其子组件可见,其它组件不可注入它;
3、模块和组件中的提供器有相同的token时(privide属性定义名称相同),组件中的提供器会覆盖模块中的;
4、提供器优先定义在模块中。
ProductService中的类有@Injectable()装饰器代表,它可以在自身的构造函数中注入别的类
@Injectable()
export class ProductService {
constructor() {
}
/* 定义getProduct方法,返回Product对象*/
getProduct(): Product {
return new Product(0,'iPhone7',5899,'新品上市,最新款');
}
}
服务之间如何注入
ng g service shared/logger
???
工厂函数来提供器
...
providers: [{
provide:ProductService,
useFactory:(logger:LoggerService,appConfig) => {
if(appConfig.isDev){
return new ProductService(logger);
}else{
return new AnotherProductService(logger);
}
},
deps:[LoggerService,"APP_CONFIG"]
},LoggerService,{
provide:"APP_CONFIG",useValue:{isDev:false}
}],
...
1、ProductService对象利用工厂函数来自动判断给product1和product2是注入ProductService还是AnotherProductService
2、useFactory中有两个参数,LoggerService是在ProductService中注入的,所以,做为参数的话,要增加deps属性来声明做为参数依赖,为可实现LoggerService的自动依赖注入,“判断代码可以在及自身内部实现”;
3、参数appConfig是依赖于APP_CONFIG对象,通过判断自身useValue属性对象中的isDev的值来判断product1和product2是注入ProductService还是AnotherProductService
注入器的层级关系
Angular中只有在构造函数的参数中提供依赖注入
export class Product2Component implements OnInit {
product:Product;//需要一个变量用于模板渲染
constructor(private productService:ProductService) { }
ngOnInit() {
/* 组件生成的生命周期函数里面 给product变量赋值 */
this.product = this.productService.getProduct();
}
}
源码:
链接: https://pan.baidu.com/s/1kVy0FJL 密码: cca7
重构auction项目,使用依赖注入
1、新建服务product
ng g service shared/product
2、模拟数组Product 和 CommentArray,提供三个方法 getProducts 查看商品列表,getProduct 通过ID查看商品详情,getCommentForProductId通过商品ID查看商品评价
...
@Injectable()
export class ProductService {
private products: Product[] = [
new Product(1, '商品1', 1.99, 3.5, '第一个商品', ['电子产品', '硬件产品']),
new Product(2, '商品2', 2.99, 4, '第二个商品', ['电子产品']),
new Product(3, '商品3', 1.89, 5, '第三个商品', ['图书']),
new Product(4, '商品4', 1.33, 4.5, '第四个商品', ['电子产品', '硬件产品']),
new Product(5, '商品5', 3.0, 2.5, '第五个商品', ['硬件产品']),
new Product(6, '商品6', 4.50, 1.5, '第六个商品', ['电子产品']),
];
private comments: CommentArray[] = [
new CommentArray(1, 1, "2017-04-12 08:12:01", "李伟", 3, "东西不错"),
new CommentArray(2, 1, "2017-04-12 23:12:11", "刘涛", 4, "质量过硬"),
new CommentArray(3, 2, "2017-04-12 15:12:11", "宗良", 5, "上次还会买"),
new CommentArray(4, 1, "2017-04-12 22:12:11", "汉洋", 2.5, "质量好差,很丑"),
new CommentArray(5, 2, "2017-04-12 11:50:11", "张和", 3.3, "凑合着用吧"),
];
constructor() {
}
/* 显示商品列表 */
getProducts(): Product[] {
return this.products;
}
/* 通过Id查看商品 */
getProduct(id: number): Product {
return this.products.find((product) => product.id == id);
}
/* 过通商品Id,获取商品的评价信息 */
getCommentForProductId(id: number): CommentArray[] {
return this.comments.filter((comment: CommentArray) => comment.productId == id);
}
}
export class Product {
constructor(public id: number,
public title: string,
public price: number,
public rating: number,
public desc: string,
public categorys: Array<string>) {
}
}
export class CommentArray {
constructor(public id: number,
public productId: number,
public timestamp: string,
public user: string,
public rating: number,
public content: string) {
}
}
3、app.module.ts中提供器声明ProductService
providers: [ProductService],
4、product组件中,constructor构造函数中注入ProductService,在ngOnInit调用getProducts方法。
...
export class ProductComponent implements OnInit {
private imgUrl = 'http://placehold.it/320x150';
private products:Product[];
constructor(private productService:ProductService ) { }
ngOnInit() {
this.products = this.productService.getProducts();
}
}
5、ProductDetail组件中,constructor中注入ActivatedRoute和ProductService,在ngOnInit中调用getProduct()和getCommentForProductId()方法。
...
export class ProductDetailComponent implements OnInit {
product:Product; //定义了一个Product类型的本地属性product(单个商品)
comments:CommentArray[];
constructor(private routeInfo:ActivatedRoute,
private productService:ProductService
) { }
ngOnInit() {
let productId:number = this.routeInfo.snapshot.params['productId'];
this.product = this.productService.getProduct(productId);
this.comments = this.productService.getCommentForProductId(productId);
}
}