找不到的API?

AngularJS提供了一些功能的封装,但是当你试图通过全局对象angular去 访问这些功能时,却发现与以往遇到的库大不相同。

  • $http

比如,在jQuery中,我们知道它的API通过一个全局对象:$ 暴露出来,当你需要 进行ajax调用时,使用$.ajax()就可以了。这样的API很符合思维的预期。

AngularJS也暴露了一个全局对象:angular,也对ajax调用进行封装提供了一个 $http对象,但是,但是,当你试图沿用旧经验访问angular.$http时,发现不是 那么回事!

仔细地查阅$http的文档,也找不到一点点的线索,从哪里可以把这个$http拿到。

  • 依赖注入/DI

事实上,AngularJS把所有的功能组件都以依赖注入的方式组织起来:

在依赖注入的模式下,所有的组件必须通过容器才能相互访问,这导致了在AngularJS中, 你必须通过一个中介才能获得某个组件的实例对象:

  1. var injector = angular.injector(['ng']);
  2. injector.invoke(function($http){
  3. //do sth. with $http
  4. });

这个中介,就是依赖注入模式中的容器,在AngularJS中,被称为:注入器。

在→_→的示例中,我们可以看到,我们已经拿到了$http对象,它其实是一个函数。

演示示例:http://www.dwz.cn/26R4S5

注入器/injector

注入器是AngularJS框架实现和应用开发的关键,这是一个DI/IoC容器的实现。

AngularJS将功能分成了不同类型的组件分别实现,这些组件有一个统称 - 供给者/provider, 下图中列出了AngularJS几个常用的内置服务:

AngularJS的组件之间不可以互相直接调用,一个组件必须通过注入器才 可以调用另一个组件。这样的好处是组件之间相互解耦,对象的整个生命周期的管理 甩给了注入器。

注入器实现了两个重要的功能:

  1. 集中存储所有provider的配方

配方其实就是:名称+类构造函数。AngularJS启动时,这些provider首先使用其配方在注入器 内注册。比如,http请求服务组件封装在$httpProvider类内,它通过"$http"这个名字在注入 器内注册。

  1. 按需提供功能组件的实例

其他组件,比如一个用户的控制器,如果需要使用http功能,使用"$http"这个名字 向注入器请求,就可以获得一个http服务实例了。

试着修改→_→的代码,查看下$compile服务到底是什么?

演示示例:http://www.dwz.cn/26R4S5

注册服务组件

从injector的角度看,组件就是一个功能提供者,因此被称为供给者/Provider。 在AngularJS中,provider以JavaScript类(构造函数)的形式封装。

服务名称通常使用一个字符串标识,比如"$http"代表http调用服务、"$rootScope"代表根 作用域对象、"$compile"代表编译服务...

Provider类要求提供一个$get函数(类工厂),injector通过调用该函数, 就可以获得服务组件的实例。

名称和类函数的组合信息,被称为配方。injector中维护一个集中的配方库, 用来按需创建不同的组件。这个配方库,其实就是一个Hash对象,key就是服务名称,value 就是类定义。

在→_→的示例中,我们定义了一个简单的服务类,这个服务类的实例就是一个字符串:“hello,world!”。 我们使用"ezHello"作为其服务名在注入器里注册,并通过注入器将这个实例显示出来。

演示示例:http://www.dwz.cn/26R4S5

获得注入器对象

要使用AngularJS的功能,必须首先获取注入器。有两种方法取得注入器。

  • 创建一个新的注入器

可以使用angular.injector()创建一个新的注入器:

  1. angular.injector(modules, [strictDi]);
  • 获取已经创建的注入器

如果AngularJS框架已经启动,那么可以使用DOM对象的injector()方法获 得已经创建的注入器:

  1. var element = angular.element(dom_element);
  2. var injector = element.injector();

通过注入器调用API

注入器有两个方法可供进行API调用:invoke()和get()。

  • invoke()

使用注入器的invoke()方法,可以直接调用一个用户自定义的函数体,并通过函数参数 注入所依赖的服务对象,这是AngularJS推荐和惯例的用法:

  1. angular.injector(['ng'])
  2. .invoke(function($http){
  3. //do sth. with $http
  4. });
  • get()

也可以使用注入器的get()方法,获得指定名称的服务实例:

  1. var my$http = angular.injector(['ng']).get('$http');
  2. //do sth. with my$http

→_→的示例这次使用了get()方法直接获取一个服务实例,感受一下!

演示示例:http://www.dwz.cn/26R4S5

注入的方式和原理

有两种方法告知注入器需要注入的服务对象:参数名注入和依赖数组注入。

  • 参数名注入

AngularJS在执行invoke()函数时,将待注入函数定义转化为字符串,通过 正则表达式检查其参数表,从而发现并注入所所依赖的服务对象:

  1. //myfunc通过参数表声明这个函数依赖于"$http"服务
  2. var myfunc = function($http){
  3. //do sth. with $http
  4. };
  5. injector.invoke(myfunc);//myfunc的定义将被转化为字符串进行参数名检查

这样有一个问题,就是当我们对JavaScript代码进行压缩处理时,$http可能会被 变更成其他名称,这将导致注入失败。

  • 依赖数组注入

AngularJS采用依赖项数组的方法解决代码压缩混淆产生的问题。这时传入invoke()的 是一个数组,数组的最后一项是实际要执行的函数,其他项则指明需要向该函数注入 的服务名称。注入器将按照数组中的顺序,依次向函数注入依赖对象。

采用这种方法,待注入函数的参数表的名称就无关紧要了:

  1. //myfunc依赖于"$http"和"$compile"服务
  2. var myfunc = ["$http","$compile",function(p1,p2){
  3. //do sth. with p1($http),p2($compile)
  4. }];
  5. injector.invoke(myfunc);

→_→的实例这次采用依赖数组的方法注入了ezHello服务实例,可以改改参数名称 看有没有影响结果?

参考资料:http://www.dwz.cn/26R4S5

AngularJS应用开发思维之3:依赖注入的更多相关文章

  1. AngularJS开发指南14:依赖注入

    推荐两种使用场景: 1.控制器中的依赖注入 控制器是负责应用行为的类.推荐的控制器声明方法如下: var MyController = function(dep1, dep2) { ... } MyC ...

  2. AngularJs:Service、Factory、Provider依赖注入使用与区别

           本教程使用AngularJS版本:1.5.3        AngularJs GitHub: https://github.com/angular/angular.js/       ...

  3. 跟我学AngularJs:Service、Factory、Provider依赖注入使用与差别

    林炳文Evankaka原创作品. 转载请注明出处http://blog.csdn.net/evankaka        本教程使用AngularJs版本号:1.5.3        AngularJ ...

  4. Angularjs学习笔记(三)----依赖注入

    一.定义 如前所述,$scope对象被神秘的注入到了控制器中,实际上,这是因为控制器声明了它需要$scope,所以AngularJS才会创建并注入它.这套依赖管理系统可以这样总结:"为了正常 ...

  5. AngularJs 学习笔记(三)依赖注入

    一个对象可以通过三种方式来获取对依赖对象的控制权: 1.在内部创建依赖的对象 2.通过全局变量引用这个依赖对象 3.通过参数进行传递(在这里是通过函数参数) AngularJs通过$injector注 ...

  6. Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor

    Webservice WCF WebApi   注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...

  7. 【.NET 6】使用.NET 6开发minimal api以及依赖注入的实现、VS2022热重载和自动反编译功能的演示

    前言: .net 6 LTS版本发布已经有若干天了.此处做一个关于使用.net 6 开发精简版webapi(minimal api)的入门教程,以及VS2022 上面的两个强大的新技能(热重载.代码自 ...

  8. Java开发学习(六)----DI依赖注入之setter及构造器注入解析

    一.DI依赖注入 首先来介绍下Spring中有哪些注入方式? 我们先来思考 向一个类中传递数据的方式有几种? 普通方法(set方法) 构造方法 依赖注入描述了在容器中建立bean与bean之间的依赖关 ...

  9. WPF PRISM开发入门二(Unity依赖注入容器使用)

    这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点 ...

随机推荐

  1. 基于RDP开源许可rdesktop基本介绍

    **************************************************************************************************** ...

  2. 【原版的】PHP技术成长规划过程中猿人

    PHP程序猿的技术成长规划 作者:黑夜路人(2014/10/15) 依照了解的非常多PHP/LNMP程序猿的发展轨迹.结合个人经验体会,抽象出非常多程序猿对未来的迷漫,特别对技术学习的盲目和慌乱.简单 ...

  3. 【iOS开发-21】UINavigationController导航控制器初始化,导航控制器栈的push和pop跳转理解

    (1)导航控制器初始化的时候一般都有一个根视图控制器,导航控制器相当于一个栈,里面装的是视图控制器,最先进去的在最以下,最后进去的在最上面.在最上面的那个视图控制器的视图就是这个导航控制器对外展示的界 ...

  4. [Linux]history 显示命令的运行时间

    显示线时间历史命令 这里的环境是centos5.8 vim ~/.bashrc 或者 ~/.bash_profile 添加 export HISTTIMEFORMAT="%F %T &quo ...

  5. JNDI-j2ee

    Database Connection Pool (DBCP) Configurations The default database connection pool implementation i ...

  6. RH253读书笔记(9)-Lab 9 Account Management Methods

    Lab 9 Account Management Methods Goal: To build skills with PAM configuration Sequence 1: Track Fail ...

  7. HTML5 获得canvas油漆环境

    笔者:本笃庆军 原文地址:http://blog.csdn.net/qingdujun/article/details/32925369 我们用的最主要的画图环境在canvas中画图.通过调用canv ...

  8. linux0.11学习笔记(2)

    makefile文件: makefile 文件是make 实用简介.make 程序是用Makefile最后一次改变的数据文件和代码文件(last-modification time)确定哪些文件需要更 ...

  9. UC浏览器插件开发

    pip install UC浏览器插件是个什么玩意? 如图所看到的,便是UC的插件面板. UC通过开放浏览器插件api, 使开发人员可以进行插件的开发. 插件种类: 1 : extension. 就是 ...

  10. NSIS常用代码整理

    原文 NSIS常用代码整理 这是一些常用的NSIS代码,少轻狂特意整理出来,方便大家随时查看使用.不定期更新哦~~~ 1 ;获取操作系统盘符 2 ReadEnvStr $R0 SYSTEMDRIVE ...