angular4学习笔记(第三章 依赖注入篇)

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>
    
    

10.界面展示

猜你喜欢

转载自blog.csdn.net/cxzlp12345/article/details/86518003