zoukankan      html  css  js  c++  java
  • Angular4.0从入门到实战打造在线竞拍网站学习笔记之三--依赖注入

    Angular4.0基础知识之组件
    Angular4.0基础知识之路由
    Angular4.0依赖注入
    Angular4.0数据绑定&管道

    依赖注入(Dependency Injection)

    正常情况下,我们写的代码应该是这样子的:

    let product = new Product();	// 实例化一个对象
    createOrder(product);	// 调用方法传入商品对象,生成订单
    

    createOrder方法依赖product类,但是createOrder方法自身并不知道也不能去创建一个product对象。我们把方法所需的对象实例化并当做参数传入,这个过程就成为把参数注入给这个方法。在此你可能看不出什么,但是如果依赖的对象比较多了呢?我们需要反复去new,反复去生成对象,然后传入到方法中......想想就是噩梦。

    那么,能不能让某人替我们创建createOrder所依赖的对象和对象所依赖的其他对象呢?如果可以的话,那么,我们只需要写一句方法的调用即可,对象都将会呗自动创建好,并当做参数传递进去(想想就很美妙,懒人必备啊)。

    也就是说,对象A只需要声明,我需要一个B类型的对象,那么这个对象就会从外部注入进来,这就是依赖注入要解决的问题。

    与依赖注入经常同时出现的另一个概念叫做控制反转(Inversion Of Control),简称IOC。

    控制反转是指将依赖的控制权从代码的内部转移到代码的外部,如上代码所示,方法所需的依赖是由方法的内部所决定的,如果需要改变依赖,就需要修改方法内部的代码,外面不管是传入Product的实例,还是传入Product子类的实例,是有方法外部决定的。

    IOC着重描述目的;DI着重描述实现的方法,即如何去实现控制反转。实现了控制反转模式的框架被称为IOC容器。

    实现依赖注入

    那么如何在Angular中实现以来注入呢?

    定义提供器

    首先,使用命令行工具生成一个service,用于提供注入服务。

    ng g service shared/product

    由于product是共享的,所以放到了一个自定义的shared文件夹

    接下来,对生成的服务进行编辑(由于当前没有对这个服务进行注册,显然不会生效)

    import {Injectable} from '@angular/core';
    
    @Injectable()
    export class ProductService {
    
      constructor() { }
    
      getProduct(): Product {
        return new Product(1, '小米Mix', 3999, '很666的手机');
      }
    
    }
    
    /**
     * 定义一个Product商品类
     */
    export class Product {
      constructor(public id: number, public title: string, public price: number, public desc: string) { }
    }
    

    下面,进入app.module,注册服务

    ...
      providers: [ProductService],
    ...
    

    在使用的时候(需要获取product对象的时候,直接在构造函数中声明需要Product类型的变量,即可完成注入。

    constructor (product:Product){  }
    

    这时候,注入提供器声明在了模块中,也可以在组件的@component()中添加providers属性,这时候,作用域就变成了当前组件,并且组件中声明的提供器比模块的优先级更高

    使用工厂声明提供器

    如果在实例化类的时候需要传递参数,或需要进行一些操作去得到一个注入对象,那么使用工厂声明一个提供器是更好的解决办法。

    providers: [{
        provide: ProductService,
        useFactory: () => {
          const dev = Math.random() > 0.5;
          if (dev) {
            return new Product(1, '小米6', 2999, '很6的手机');
          } else {
            return new Product(2, '小米mix', 3999, '很美的手机');
          }
        }
      }],
    

    那么,如果工厂方法依赖一个LoggerService,我们如何去解耦合并把loggerServices注入到工厂方法呢?需要使用第三个参数:

    providers: [{
        provide: ProductService,
        useFactory: (logger:LoggerService) => {
          const dev = Math.random() > 0.5;
          if (dev) {
            return new Product(1, '小米6', 2999, '很6的手机');
          } else {
            return new Product(2, '小米mix', 3999, '很美的手机');
          }
        },
        deps:[LoggerService]
      },LoggerService],
    

    如此,即可实现工厂方法的依赖注入

    使用具体的值定义提供器

    providers: [{
        provide: ProductService,
        useFactory: (logger:LoggerService,appConfig) => {
          if (appConfig.isDev) {
            return new Product(1, '小米6', 2999, '很6的手机');
          } else {
            return new Product(2, '小米mix', 3999, '很美的手机');
          }
        },
        deps:[LoggerService,"APP_CONFIG"]
      },LoggerService,{
      	provide:"APP_CONFIG",
    	useValue:{isDev:false}
      }],
    

    注意,被注入的类都需要有一个@Injectable()装饰器,这样才能被注入

    那么你可能会疑惑了,angular组件控制器的类并没有@Injecdtable()装饰器,但是构造函数却能被注入,这是因为@component()装饰器的实现一键集成了@Injectable()

    为了更容易理解,接下来实现一下手工注入:

    import {Injector} from '@angular/core';
    
    export class ProductComponent implements OnInit {
    
      private product: ProductService;
    
      constructor(private injector: Injector) {
        this.product = injector.get(ProductService);
      }
    }
    

    Angular的依赖注入只有一个注入点,也就是构造函数。

  • 相关阅读:
    Windows vm install MAC OS
    DragonBones cpp
    APK .
    cocos2D-X vs2015 lua project 断点调试
    为什么前后端分离了,你比从前更痛苦?
    CSS3中一些鲜为人知的属性
    Web认证_介绍Web开发中几种常用的认证机制
    基于JWT的Token认证机制实现及安全问题
    别了,JavaScript;你好WebAssembly
    css设置全屏背景图,background-size 属性
  • 原文地址:https://www.cnblogs.com/wxjblog/p/7275005.html
Copyright © 2011-2022 走看看