Angular 理解module和injector,即依赖注入


Posted in Javascript onSeptember 07, 2016

依赖注入(DI)的好处不再赘言,使用过spring框架的都知道。angularjs作为前台js框架,也提供了对DI的支持,这是javascript/jquery不具备的特性。angularjs中与DI相关有angular.module()、angular.injector()、 $injector、$provide。对于一个DI容器来说,必须具备3个要素:服务的注册、依赖关系的声明、对象的获取。比如spring中,服务的注册是通过xml配置文件的<bean>标签或是注解@Repository、@Service、@Controller、@Component实现的;对象的获取可以ApplicationContext.getBean()实现;依赖关系的声明,即可以在xml文件中配置,也可以使用@Resource等注解在java代码中声明。在angular中,module和$provide相当于是服务的注册;injector用来获取对象(angular会自动完成依赖的注入);依赖关系的声明在angular中有3种方式。下面从这3个方面,介绍下angular的DI。

1、angular.module()创建、获取、注册angular中的模块

The angular.module() is a global place for creating, registering and retrieving Angular modules.When passed two or more arguments, a new module is created. If passed only one argument, an existing module (the name passed as the first argument to module) is retrieved。

// 传递参数不止一个,代表新建模块;空数组代表该模块不依赖其他模块
var createModule = angular.module("myModule", []);

// 只有一个参数(模块名),代表获取模块
// 如果模块不存在,angular框架会抛异常
var getModule = angular.module("myModule");

// true,都是同一个模块
alert(createModule == getModule);

该函数既可以创建新的模块,也可以获取已有模块,是创建还是获取,通过参数的个数来区分。

angular.module(name, [requires], [configFn]);

name:字符串类型,代表模块的名称;

requires:字符串的数组,代表该模块依赖的其他模块列表,如果不依赖其他模块,用空数组即可;

configFn:用来对该模块进行一些配置。

现在我们知道如何创建、获取模块了,那么模块究竟是什么呢?官方的Developer Guide上只有一句话:You can think of a module as a container for the different parts of your app ? controllers, services, filters, directives, etc.现在我还不太理解,大致就是说模块是一些功能的集合,如控制器、服务、过滤器、指令等子元素组成的整体。现在解释不了,先遗留。

2、$provide和模块的关系

The $provide service has a number of methods for registering components with the $injector. Many of these functions are also exposed on angular.Module.

之前提到过:module和provide是用来注册服务到injector中的。查看官方的API,可以看到$provide提供了provide()、constant()、value()、factory()、service()来创建各种不同性质的服务;angular.Module中也提供了这5个服务注册方法。其实2者功能是完全一样的,就是用来向DI容器注册服务到injector中。

官方API下的auto有$provide 和 $injector,Implicit module which gets automatically added to each $injector.按照字面意思是说,每一个injector都有这2个隐含的服务。但1.2.25版本中,感觉没有办法获取injector中的$provide。不知道这是为什么?一般来说也不需要显示使用这个服务,直接使用module中提供的API即可。

var injector = angular.injector();
alert(injector.has("$provide"));//false
alert(injector.has("$injector"));//true

3、angular.injector()

使用angular.injector();也能获取到注入器,但是没有和模块绑定。这种做法是没有意义的,相当于是你创建了一个空的DI容器,里面都没有服务别人怎么用呢。正确的做法是,在创建注入器的时候,指定需要加载的模块。

// 创建myModule模块、注册服务
var myModule = angular.module('myModule', []);
myModule.service('myService', function() {
  this.my = 0;
});

// 创建herModule模块、注册服务
var herModule = angular.module('herModule', []);
herModule.service('herService', function() {
  this.her = 1;
});

// 加载了2个模块中的服务
var injector = angular.injector(["myModule","herModule"]);
alert(injector.get("myService").my);
alert(injector.get("herService").her);

如果加载了多个模块,那么通过返回的injector可以获取到多个模块下的服务。这个例子中如果只加载了myMoudle,那么得到的injector就不能访问herMoudle下的服务。这里特别需要注意下:angular.injector()可以调用多次,每次都返回新建的injector对象。

var injector1 = angular.injector(["myModule","herModule"]);
var injector2 = angular.injector(["myModule","herModule"]);

alert(injector1 == injector2);//false

4、angular中三种声明依赖的方式

angular提供了3种获取依赖的方式:inference、annotation、inline方式。

// 创建myModule模块、注册服务
var myModule = angular.module('myModule', []);
myModule.service('myService', function() {
  this.my = 0;
});

// 获取injector
var injector = angular.injector(["myModule"]);

// 第一种inference
injector.invoke(function(myService){alert(myService.my);});

// 第二种annotation
function explicit(serviceA) {alert(serviceA.my);};
explicit.$inject = ['myService'];
injector.invoke(explicit);

// 第三种inline
injector.invoke(['myService', function(serviceA){alert(serviceA.my);}]);

其中annotation和inline方式,对于函数参数名称没有要求,是推荐的做法;inference方式强制要求参数名称和服务名称一致,如果JS代码经过压缩或者混淆,那么功能会出问题,不建议使用这种方式。

以上就是对Angular JS依赖注入的资料整理,后续继续补充相关资料,谢谢大家对本站的支持!

Javascript 相关文章推荐
用JavaScript实现UrlEncode和UrlDecode的脚本代码
Jul 23 Javascript
JQuery Tips(2) 关于$()包装集你不知道的
Dec 14 Javascript
jQuery EasyUI API 中文文档 - Calendar日历使用
Oct 19 Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
Nov 14 Javascript
javascript数组详解
Oct 22 Javascript
JS实现将数字金额转换为大写人民币汉字的方法
Aug 02 Javascript
详解JavaScript模块化开发
Dec 04 Javascript
基于VUE选择上传图片并页面显示(图片可删除)
May 25 Javascript
vue轮播图插件vue-concise-slider的使用
Mar 13 Javascript
JS中this的4种绑定规则详解
Feb 04 Javascript
flexible.js实现移动端rem适配方案
Apr 07 Javascript
Vue中inheritAttrs的使用实例详解
Dec 31 Vue.js
JS继承之借用构造函数继承和组合继承
Sep 07 #Javascript
Node.js读写文件之批量替换图片的实现方法
Sep 07 #Javascript
jQuery实现底部浮动窗口效果
Sep 07 #Javascript
聊一聊Vue.js过渡效果
Sep 07 #Javascript
BootStrap中的表单大全
Sep 07 #Javascript
JS实现title标题栏文字不间断滚动显示效果
Sep 07 #Javascript
JavaScript 函数模式详解及示例
Sep 07 #Javascript
You might like
中国广播史趣谈 — 几个历史第一次
2021/03/01 无线电
php preg_replace替换实例讲解
2013/11/04 PHP
php smarty truncate UTF8乱码问题解决办法
2014/06/13 PHP
php+redis在实际项目中HTTP 500: Internal Server Error故障排除
2017/02/05 PHP
this[] 指的是什么内容 讨论
2007/03/24 Javascript
JavaScript入门学习书籍推荐
2008/06/12 Javascript
js 通用订单代码
2013/12/23 Javascript
javascript校验价格合法性实例(必须输入2位小数)
2014/05/05 Javascript
js实现弹出窗口、页面变成灰色并不可操作的例子分享
2014/05/10 Javascript
vue插件tab选项卡使用小结
2016/10/27 Javascript
解决JSON.stringify()自动将中文转译成unicode的问题
2018/01/05 Javascript
利用Console来Debug的10个高级技巧汇总
2018/03/26 Javascript
JS中判断某个字符串是否包含另一个字符串的五种方法
2018/05/03 Javascript
vue 使用自定义指令实现表单校验的方法
2018/08/28 Javascript
vue-router 前端路由之路由传值的方式详解
2019/04/30 Javascript
swiper4实现移动端导航切换
2020/10/16 Javascript
Vue(定时器)解决mounted不能获取到data中的数据问题
2020/07/30 Javascript
在python中的socket模块使用代理实例
2014/05/29 Python
python实现感知器算法详解
2017/12/19 Python
用python处理图片实现图像中的像素访问
2018/05/04 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
程序员写Python时的5个坏习惯,你有几条?
2018/11/26 Python
Python构建图像分类识别器的方法
2019/01/12 Python
彻底理解Python中的yield关键字
2019/04/01 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
python collections模块的使用
2020/10/16 Python
详解canvas多边形(蜘蛛图)的画法示例
2018/01/29 HTML / CSS
小学新学期教师寄语
2014/01/18 职场文书
生产部管理制度
2014/01/31 职场文书
《凡卡》教学反思
2014/04/09 职场文书
《鸟岛》教学反思
2014/04/26 职场文书
食品安全标语
2014/06/07 职场文书
驻村工作简报
2015/07/20 职场文书
2015年中秋晚会主持稿
2015/07/30 职场文书
2016国培研修心得体会
2016/01/08 职场文书
MySQL实现配置主从复制项目实践
2022/03/31 MySQL