AngularJS应用开发思维之依赖注入3


Posted in Javascript onAugust 19, 2016

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

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

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

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

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

AngularJS应用开发思维之依赖注入3

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

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

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

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

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

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

AngularJS应用开发思维之依赖注入3

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

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

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

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

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

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

AngularJS应用开发思维之依赖注入3

服务名称通常使用一个字符串标识,比如'$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服务实例,可以改改参数名称 看有没有影响结果?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
纯JS实现动态时间显示代码
Feb 08 Javascript
js调用iframe实现打印页面内容的方法
Mar 04 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
Sep 12 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
Dec 11 Javascript
mui框架 页面无法滚动的解决方法(推荐)
Jan 25 Javascript
浅析java线程中断的办法
Jul 29 Javascript
node链接mongodb数据库的方法详解【阿里云服务器环境ubuntu】
Mar 07 Javascript
JS实现水平移动与垂直移动动画
Dec 19 Javascript
在weex中愉快的使用scss的方法步骤
Jan 02 Javascript
VueQuillEditor富文本上传图片(非base64)
Jun 03 Javascript
js调用网络摄像头的方法
Dec 05 Javascript
JavaScript原型链详解
Nov 07 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
Aug 19 #Javascript
js 获取当前web应用的上下文路径实现方法
Aug 19 #Javascript
AngularJS入门教程之路由与多视图详解
Aug 19 #Javascript
AngularJS入门教程之链接与图片模板详解
Aug 19 #Javascript
AngularJS之依赖注入模拟实现
Aug 19 #Javascript
AngularJS入门教程之XHR和依赖注入详解
Aug 18 #Javascript
JavaScript中函数声明与函数表达式的区别详解
Aug 18 #Javascript
You might like
造就帕卡马拉的帕卡斯是怎么被发现的
2021/03/03 咖啡文化
php使用Smarty的相关注意事项及访问变量的几种方式
2011/12/08 PHP
基于php验证码函数的使用示例
2013/05/03 PHP
关于php操作mysql执行数据库查询的一些常用操作汇总
2013/06/24 PHP
ThinkPHP模板判断输出Present标签用法详解
2014/06/30 PHP
推荐25款php中非常有用的类库
2014/09/29 PHP
PHP实现图片批量打包下载功能
2017/03/01 PHP
javascript获取ckeditor编辑器的值(实现代码)
2013/11/18 Javascript
JSON无限折叠菜单编写实例
2013/12/16 Javascript
jQuery之ajax删除详解
2014/02/27 Javascript
js 判断图片是否加载完以及实现图片的预下载
2014/08/14 Javascript
jQuery幻灯片带缩略图轮播效果代码分享
2015/08/17 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
2016/05/12 Javascript
原生JS实现的雪花飘落动画效果
2018/05/03 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
2019/12/20 Javascript
vue项目中使用bpmn-自定义platter的示例代码
2020/05/11 Javascript
解决Echarts 显示隐藏后宽度高度变小的问题
2020/07/19 Javascript
Vue中 axios delete请求参数操作
2020/08/25 Javascript
python调用cmd命令行制作刷博器
2014/01/13 Python
利用Python的装饰器解决Bottle框架中用户验证问题
2015/04/24 Python
使用python读取txt文件的内容,并删除重复的行数方法
2018/04/18 Python
tensorflow学习教程之文本分类详析
2018/08/07 Python
Python面向对象类编写细节分析【类,方法,继承,超类,接口等】
2019/01/05 Python
用python做游戏的细节详解
2019/06/25 Python
解决Python3 控制台输出InsecureRequestWarning问题
2019/07/15 Python
python根据字典的键来删除元素的方法
2020/08/16 Python
浅谈html5增强的页面元素
2016/06/14 HTML / CSS
NYX Professional Makeup英国官网:美国平价专业彩妆品牌
2019/11/13 全球购物
丝芙兰意大利官方网站:Sephora.it
2019/12/13 全球购物
俄罗斯商务邀请函
2014/01/26 职场文书
小学防溺水制度
2014/01/29 职场文书
英语老师推荐信
2014/02/26 职场文书
煤矿安全生产月活动总结
2014/07/05 职场文书
小学二年级数学教学计划
2015/01/20 职场文书
python 逐步回归算法
2021/04/06 Python
Java并发编程之详解CyclicBarrier线程同步
2021/06/23 Java/Android