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 - HTML的request类
Jul 15 Javascript
jQuery对表单的操作代码集合
Apr 06 Javascript
使用jQuery处理AJAX请求的基础学习教程
May 10 Javascript
当jquery ajax遇上401请求的解决方法
May 19 Javascript
jQuery基本过滤选择器用法示例
Sep 09 Javascript
一文让你彻底搞清楚javascript中的require、import与export
Sep 24 Javascript
详解ESLint在Vue中的使用小结
Oct 15 Javascript
vue项目搭建以及全家桶的使用详细教程(小结)
Dec 19 Javascript
详解ng-alain动态表单SF表单项设置必填和正则校验
Jun 11 Javascript
jQuery提示框插件SweetAlert用法分析
Aug 05 jQuery
Node.js开发之套接字(socket)编程入门示例
Nov 05 Javascript
解决vuex刷新数据消失问题
Nov 12 Javascript
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
虫族 Zerg 魔法科技
2020/03/14 星际争霸
php实现在线生成条形码示例分享(条形码生成器)
2013/12/30 PHP
ThinkPHP路由详解
2015/07/27 PHP
php  PATH_SEPARATOR判断当前服务器系统类型实例
2016/10/28 PHP
Yii框架批量插入数据扩展类的简单实现方法
2017/05/23 PHP
PHP中“=&gt;
2019/03/01 PHP
php用wangeditor3实现图片上传功能
2019/08/22 PHP
PHP实现限制域名访问的实现代码(本地验证)
2020/09/13 PHP
javascript 火狐(firefox)不显示本地图片问题解决
2008/07/05 Javascript
响应鼠标变换表格背景或者颜色的代码
2009/03/30 Javascript
文本框获得焦点和失去焦点的判断代码
2012/03/18 Javascript
JS的replace方法详细介绍
2012/11/09 Javascript
jquery插件之信息弹出框showInfoDialog(成功/错误/警告/通知/背景遮罩)
2013/01/09 Javascript
Javascript浮点数乘积运算出现多位小数的解决方法
2014/02/17 Javascript
js实现的复制兼容chrome和IE
2014/04/03 Javascript
jQuery学习笔记之toArray()
2014/06/09 Javascript
基于JavaScript实现移动端点击图片查看大图点击大图隐藏
2015/11/04 Javascript
jquery.zclip轻量级复制失效问题
2017/01/08 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
微信小程序商品详情页的底部弹出框效果
2020/11/16 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
2018/10/01 Javascript
微信小程序聊天功能的示例代码
2020/01/13 Javascript
[02:35]DOTA2英雄基础教程 末日使者
2013/12/04 DOTA
[08:56]DOTA2-DPC中国联赛2月23日Recap集锦
2021/03/11 DOTA
python中nan与inf转为特定数字方法示例
2017/05/11 Python
浅谈python的dataframe与series的创建方法
2018/11/12 Python
python实现抠图给证件照换背景源码
2019/08/20 Python
Django将默认的SQLite更换为MySQL的实现
2019/11/18 Python
tensorflow之并行读入数据详解
2020/02/05 Python
python计算导数并绘图的实例
2020/02/29 Python
Python的轻量级ORM框架peewee使用教程
2021/02/05 Python
美国名牌手表折扣网站:Jomashop
2020/05/22 全球购物
自动化专业毕业生自荐信
2013/11/01 职场文书
《跨越海峡的生命桥》教学反思
2014/02/24 职场文书
2016年社区“我们的节日·中秋节”活动总结
2016/04/05 职场文书
新手必备之MySQL msi版本下载安装图文详细教程
2021/05/21 MySQL