1.依赖注入
- 依赖注入是什么?
- 依赖注入是“控制反转”(将实例化这个类的控制权交给外部,从而实现类与组件的解耦)的一体两面。控制反转是目的,依赖注入是手段。是不是不太明白,说得直白一点就是在程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。
- 依赖注入怎么用?
- 我们在组件需要某个服务的实例时,不需要手动创建这个实例,只需要在构造函数的参数中指定这个实例的变量,以及这个实例的类,然后angular会根据这个类的名字找到providers属性中指定的同名的provide,再找到它对应的useclass,最终自动创建这个服务的实例。
- 依赖注入的好处
- 在Angular中使用依赖注入,可以帮助我们实现松耦合,实现组件的可重用性。
- 这里就不多介绍依赖注入了,如果对依赖注入不理解的可以看看该博客内容(https://blog.csdn.net/it_rod/article/details/79370839)
2.注入器
- angular只有一种注入方式——在组件的构造函数中注入
3.提供器
- 需要依赖注入的东西(一般为服务),需要声明在提供器中才能被注入
- 提供器的使用方法(其中provide和useClass本人认为相当于一个键值对,provide通常作为一个“token”使用,相当于一个键名,而useClass通常是需要实例化的对象,相当于一个值)
// 只有当provide与useClass的值一样时才能使用这样的简写 providers: [ProductService] // 与上面的写法具有同样的效果 providers: [{provide: ProductService, useClass: ProductService}] // 当provide与useClass的值一样时的写法 providers: [{provide: ProductService, useClass: AnotherProductService}] // 用工厂方式创建这个实例(单一) providers: [{provide: ProductService, useFactory: ()=>{...}}] // 使用useValue的写法 provides: [{provide: 'USE-VALUE', useValue: "value"} ]
4.useClass的用法(两属性值相同)
- 创建一个商品服务
- 在模块中提供该服务,用于模块内所有组件
- 在组件的构造函数中注入服务
- 显示在界面上
- 显示结果
5.useClass的用法(两属性值不相同)
- 创建商品服务1,实现商品服务的接口
- 在模块中提供服务
- 在组件中注入服务
- 显示在界面上
- 显示结果
6.useFactory的用法
- 在声明提供器的时候使用useFactory,根据isOther字段判断provide(token)为"ProductService"实例化哪个对象,工厂方法比较单一,只能实例化一个对象。
- 如果想在提供器服务中注入其他的服务,使用deps属性
7.useValue的用法
- 使用useValue方法代替上面的isOther声明
8.注入器层级关系
- 声明在app.module.ts中的provides的注入可以用于该模块下所有组件
- 声明在服务中的@Injectable()中
- 在组件中声明,会覆盖在模块中的声明,优先级更高
9.更新上次界面的代码
- 编写一个商品服务 ng g s product
import { Injectable } from '@angular/core'; // 注入到根模块中,所有组件都可以调用,此方法无需再app.module.ts中再提供该服务 @Injectable({ providedIn: 'root' }) export class ProductService { // 商品数据 public products: Products[] = [ new Products(1, '第一个商品', 1.99, '这是第一个商品,相关的商品信息', 1.5, ['手机', '苹果']), new Products(2, '第二个商品', 2.99, '这是第二个商品,相关的商品信息', 2.5, ['手机', '苹果']), new Products(3, '第三个商品', 3.99, '这是第三个商品,相关的商品信息', 3.5, ['手机', '苹果']), new Products(4, '第四个商品', 4.99, '这是第四个商品,相关的商品信息', 4.5, ['手机', '苹果']), new Products(5, '第五个商品', 5.99, '这是第五个商品,相关的商品信息', 3.5, ['手机', '苹果']), new Products(6, '第六个商品', 6.99, '这是第六个商品,相关的商品信息', 2.5, ['手机', '苹果']), new Products(7, '第七个商品', 7.99, '这是第七个商品,相关的商品信息', 1.5, ['手机', '苹果'])]; // 评论数据 public comments: Comment[] = [ new Comment(1, 1, '2019-01-19 14:35:25', '张三', 4, '张三的评论内容'), new Comment(2, 1, '2019-01-18 14:25:15', '张四', 3, '张四的评论内容'), new Comment(3, 3, '2019-01-17 14:15:05', '张五', 2, '张五的评论内容'), new Comment(4, 2, '2019-01-16 14:45:35', '张六', 1, '张六的评论内容'), new Comment(5, 6, '2019-01-15 14:55:45', '张七', 3, '张七的评论内容'), ] constructor() { } // 获取商品信息 getProducts() { return this.products; } // 根据商品id获取商品信息 getProductById(id: number): Products { return this.products.find((products => products.id == id)); } // 根据商品id获取评论信息 getCommentById(id: number): Comment[] { return this.comments.filter((comment: Comment) => comment.productId == id); } } // 商品类 export class Products { constructor( public id: number, public name: string, public price: number, public desc: string, public rating: number, public type: Array<string> ) { } } // 评论类 export class Comment { constructor( public id: number, public productId: number, public time: string, public user: string, public rating: number, public content: string ) { } }
-
在商品控制器中注入商品服务,获取商品信息
import { Component, OnInit } from '@angular/core'; import { ProductService, Products } from 'src/shared/product.service'; @Component({ selector: 'app-product', templateUrl: './product.component.html', styleUrls: ['./product.component.css'] }) export class ProductComponent implements OnInit { // 声明变量接收商品信息 public products: Products[]; // 注入商品服务 constructor(private _ProductService: ProductService) { } ngOnInit() { // 使用商品服务的getProducts()方法获取商品信息 this.products = this._ProductService.getProducts(); } }
-
在商品详情控制器中注入商品服务,获取确切商品信息和该商品相关评论信息
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; import { ProductService, Products, Comment } from 'src/shared/product.service'; @Component({ selector: 'app-detialproduct', templateUrl: './detialproduct.component.html', styleUrls: ['./detialproduct.component.css'] }) export class DetialproductComponent implements OnInit { // 声明变量接收参数 private productName: string; private productId: number; private productinfo: Products; private commentinfo: Comment[]; private hasComment: boolean; // 注入商品服务 constructor(private routerinfo: ActivatedRoute, private _ProductService: ProductService) { } ngOnInit() { // 使用参数订阅方式获取数据 // 以为此处确定不会自身路由到自身路由,所以选择使用参数快照方式 // this.routerinfo.params.subscribe((params : Params) => this.productName = params['name'] ); // this.routerinfo.params.subscribe((params : Params) => this.productId = params['id'] ); // 使用参数快照方式获取数据 this.productName = this.routerinfo.snapshot.params['name']; this.productId = this.routerinfo.snapshot.params['id']; // 使用商品服务的getProductById()方法获取商品详情信息 this.productinfo = this._ProductService.getProductById(this.productId); // 使用商品服务的getCommentById()方法获取商品相关评论信息 this.commentinfo = this._ProductService.getCommentById(this.productId); // 判断是否有评论信息 if (this.commentinfo.length < 1) { this.hasComment = false; } else { this.hasComment = true; } } }
-
改写商品模板界面
<div class="row"> <div class="col-lg-4 col-md-4 col-xs-12" *ngFor="let product of products"> <div class="thumbnail"> <img src=" https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3671643272,946673945&fm=26&gp=0.jpg" alt=""> <div class="caption"> <h3 class="pull-right">¥{{product.price}}</h3> <!-- 点击商品名称跳转到商品详情页,传递两个参数id,name --> <a [routerLink]="[ '/detialproduct', product.id , product.name ]"><h3>{{product.name}}</h3></a> <p>{{product.desc}}</p> <p> <!--星级评价的rating属性由产品的rating属性传进去--> <app-stars [rating]="product.rating"></app-stars> <span> {{product.rating}} 星</span> </p> </div> </div> </div> </div>
-
改写商品详情模板界面
<div class="row"> <img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3671643272,946673945&fm=26&gp=0.jpg" alt=""> </div> <hr> <!-- 商品详情 --> <div class="thumbnail"> <div class="caption"> <span class="pull-right text-info">¥{{productinfo.price}}</span> <p>{{productinfo.name}}</p> <p> <app-stars [rating]="productinfo.rating"></app-stars> <span> {{productinfo.rating}} 星</span> </p> </div> </div> <hr> <!-- 相关评论 --> <div class="panel panel-default" *ngFor="let comments of commentinfo"> <div class="panel-heading"> <h4> 用户:{{comments.user}} </h4> <p> <app-stars [rating]="comments.rating"></app-stars> <span> {{comments.rating}} 星</span> </p> </div> <div class="panel-body"> <p>评分内容:{{comments.content}}</p> <span class="pull-right">评分时间:{{comments.time}}</span> </div> </div> <div class="panel panel-default" *ngIf="!hasComment"> <div class="panel-heading"> <h3>暂无评论</h3> </div> <div class="panel-body"> 该商品暂无相关评论信息 </div> </div>