AngularJS应用开发思维之3:依赖注入
找不到的API?
AngularJS提供了一些功能的封装,但是当你试图通过全局对象angular去 访问这些功能时,却发现与以往遇到的库大不相同。
- $http
比如,在jQuery中,我们知道它的API通过一个全局对象:$ 暴露出来,当你需要 进行ajax调用时,使用$.ajax()就可以了。这样的API很符合思维的预期。
AngularJS也暴露了一个全局对象:angular,也对ajax调用进行封装提供了一个 $http对象,但是,但是,当你试图沿用旧经验访问angular.$http时,发现不是 那么回事!
仔细地查阅$http的文档,也找不到一点点的线索,从哪里可以把这个$http拿到。
- 依赖注入/DI
事实上,AngularJS把所有的功能组件都以依赖注入的方式组织起来:
在依赖注入的模式下,所有的组件必须通过容器才能相互访问,这导致了在AngularJS中, 你必须通过一个中介才能获得某个组件的实例对象:
- var injector = angular.injector(['ng']);
- injector.invoke(function($http){
- //do sth. with $http
- });
这个中介,就是依赖注入模式中的容器,在AngularJS中,被称为:注入器。
在→_→的示例中,我们可以看到,我们已经拿到了$http对象,它其实是一个函数。
注入器/injector
注入器是AngularJS框架实现和应用开发的关键,这是一个DI/IoC容器的实现。
AngularJS将功能分成了不同类型的组件分别实现,这些组件有一个统称 - 供给者/provider, 下图中列出了AngularJS几个常用的内置服务:
AngularJS的组件之间不可以互相直接调用,一个组件必须通过注入器才 可以调用另一个组件。这样的好处是组件之间相互解耦,对象的整个生命周期的管理 甩给了注入器。
注入器实现了两个重要的功能:
- 集中存储所有provider的配方
配方其实就是:名称+类构造函数。AngularJS启动时,这些provider首先使用其配方在注入器 内注册。比如,http请求服务组件封装在$httpProvider类内,它通过"$http"这个名字在注入 器内注册。
- 按需提供功能组件的实例
其他组件,比如一个用户的控制器,如果需要使用http功能,使用"$http"这个名字 向注入器请求,就可以获得一个http服务实例了。
试着修改→_→的代码,查看下$compile服务到底是什么?
注册服务组件
从injector的角度看,组件就是一个功能提供者,因此被称为供给者/Provider。 在AngularJS中,provider以JavaScript类(构造函数)的形式封装。
服务名称通常使用一个字符串标识,比如"$http"代表http调用服务、"$rootScope"代表根 作用域对象、"$compile"代表编译服务...
Provider类要求提供一个$get函数(类工厂),injector通过调用该函数, 就可以获得服务组件的实例。
名称和类函数的组合信息,被称为配方。injector中维护一个集中的配方库, 用来按需创建不同的组件。这个配方库,其实就是一个Hash对象,key就是服务名称,value 就是类定义。
在→_→的示例中,我们定义了一个简单的服务类,这个服务类的实例就是一个字符串:“hello,world!”。 我们使用"ezHello"作为其服务名在注入器里注册,并通过注入器将这个实例显示出来。
获得注入器对象
要使用AngularJS的功能,必须首先获取注入器。有两种方法取得注入器。
- 创建一个新的注入器
可以使用angular.injector()创建一个新的注入器:
- angular.injector(modules, [strictDi]);
- 获取已经创建的注入器
如果AngularJS框架已经启动,那么可以使用DOM对象的injector()方法获 得已经创建的注入器:
- var element = angular.element(dom_element);
- var injector = element.injector();
通过注入器调用API
注入器有两个方法可供进行API调用:invoke()和get()。
- invoke()
使用注入器的invoke()方法,可以直接调用一个用户自定义的函数体,并通过函数参数 注入所依赖的服务对象,这是AngularJS推荐和惯例的用法:
- angular.injector(['ng'])
- .invoke(function($http){
- //do sth. with $http
- });
- get()
也可以使用注入器的get()方法,获得指定名称的服务实例:
- var my$http = angular.injector(['ng']).get('$http');
- //do sth. with my$http
→_→的示例这次使用了get()方法直接获取一个服务实例,感受一下!
注入的方式和原理
有两种方法告知注入器需要注入的服务对象:参数名注入和依赖数组注入。
- 参数名注入
AngularJS在执行invoke()函数时,将待注入函数定义转化为字符串,通过 正则表达式检查其参数表,从而发现并注入所所依赖的服务对象:
- //myfunc通过参数表声明这个函数依赖于"$http"服务
- var myfunc = function($http){
- //do sth. with $http
- };
- injector.invoke(myfunc);//myfunc的定义将被转化为字符串进行参数名检查
这样有一个问题,就是当我们对JavaScript代码进行压缩处理时,$http可能会被 变更成其他名称,这将导致注入失败。
- 依赖数组注入
AngularJS采用依赖项数组的方法解决代码压缩混淆产生的问题。这时传入invoke()的 是一个数组,数组的最后一项是实际要执行的函数,其他项则指明需要向该函数注入 的服务名称。注入器将按照数组中的顺序,依次向函数注入依赖对象。
采用这种方法,待注入函数的参数表的名称就无关紧要了:
- //myfunc依赖于"$http"和"$compile"服务
- var myfunc = ["$http","$compile",function(p1,p2){
- //do sth. with p1($http),p2($compile)
- }];
- injector.invoke(myfunc);
→_→的实例这次采用依赖数组的方法注入了ezHello服务实例,可以改改参数名称 看有没有影响结果?
AngularJS应用开发思维之3:依赖注入的更多相关文章
- AngularJS开发指南14:依赖注入
推荐两种使用场景: 1.控制器中的依赖注入 控制器是负责应用行为的类.推荐的控制器声明方法如下: var MyController = function(dep1, dep2) { ... } MyC ...
- AngularJs:Service、Factory、Provider依赖注入使用与区别
本教程使用AngularJS版本:1.5.3 AngularJs GitHub: https://github.com/angular/angular.js/ ...
- 跟我学AngularJs:Service、Factory、Provider依赖注入使用与差别
林炳文Evankaka原创作品. 转载请注明出处http://blog.csdn.net/evankaka 本教程使用AngularJs版本号:1.5.3 AngularJ ...
- Angularjs学习笔记(三)----依赖注入
一.定义 如前所述,$scope对象被神秘的注入到了控制器中,实际上,这是因为控制器声明了它需要$scope,所以AngularJS才会创建并注入它.这套依赖管理系统可以这样总结:"为了正常 ...
- AngularJs 学习笔记(三)依赖注入
一个对象可以通过三种方式来获取对依赖对象的控制权: 1.在内部创建依赖的对象 2.通过全局变量引用这个依赖对象 3.通过参数进行传递(在这里是通过函数参数) AngularJs通过$injector注 ...
- 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平台下, ...
- 【.NET 6】使用.NET 6开发minimal api以及依赖注入的实现、VS2022热重载和自动反编译功能的演示
前言: .net 6 LTS版本发布已经有若干天了.此处做一个关于使用.net 6 开发精简版webapi(minimal api)的入门教程,以及VS2022 上面的两个强大的新技能(热重载.代码自 ...
- Java开发学习(六)----DI依赖注入之setter及构造器注入解析
一.DI依赖注入 首先来介绍下Spring中有哪些注入方式? 我们先来思考 向一个类中传递数据的方式有几种? 普通方法(set方法) 构造方法 依赖注入描述了在容器中建立bean与bean之间的依赖关 ...
- WPF PRISM开发入门二(Unity依赖注入容器使用)
这篇博客将通过一个控制台程序简单了解下PRISM下Unity依赖注入容器的使用.我已经创建了一个例子,通过一个控制台程序进行加减乘除运算,项目当中将输入输出等都用接口封装后,结构如下: 当前代码可以点 ...
随机推荐
- mac eclipse svn subeclipse: Failed to load JavaHL Library.
Failed to load JavaHL Library. These are the errors that were encountered: no libsvnjavahl-1 in java ...
- LeetCode Solutions : Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2-& ...
- Demo of Python "Map Reduce Filter"
Here I share with you a demo for python map, reduce and filter functional programming thatowned by m ...
- 读书笔记之SQL注入漏洞和SQL调优
原文:读书笔记之SQL注入漏洞和SQL调优 最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“' ...
- iOS 要定义自己的导航栏button样式Button Image 执行出彩是不一样的与原来的颜色 -解
在相机闪光灯,在导航栏中自己定义"闪"样式.点击变换的图像期望,但一直没有变化.原来是该条款的Global Tint颜色.因此,系统会自己主动改变图片的颜色Global Tint颜 ...
- 使用SQLServer 2008的CDC功能实现数据变更捕获
原文:使用SQLServer 2008的CDC功能实现数据变更捕获 最近由于工作需要,研究了一下2008 CDC功能,觉得还不错,下面整理了一下研究过程,虽然比较粗略,但是基本上能用了,如果有补充请大 ...
- Android4.0 Design之UI设计缺陷1
我想成为Android卓越发展project联赛,不知道Android它如何设计规则,Android4.0谷歌公司的问世后Android一系列的设计原则,程序猿规范,不要盲目模仿IOS它的设计,由于A ...
- Grant的时候报错的解决:Access denied for user 'root'@'localhost' (using password: YES)
mysql> grant all on *.* to 'root'@'192.168.1.1' identified by 'password'; ERROR 1045 (28000): Acc ...
- ORM-Dapper+DapperExtensions
ORM-Dapper+DapperExtensions 现在成熟的ORM比比皆是,这里只介绍Dapper的使用(最起码我在使用它,已经运用到项目中,小伙伴们反馈还可以). 优点: 1.开源.轻量.小巧 ...
- (大数据工程师学习路径)第一步 Linux 基础入门----数据流重定向
介绍 开始对重定向这个概念感到些许陌生,但通过前面的课程中多次见过>或>>操作了,并知道他们分别是将标准输出导向一个文件或追加到一个文件中.这其实就是重定向,将原本输出到标准输出的数 ...