@frank-shaw
2016-09-22T11:33:27.000000Z
字数 3887
阅读 2085
angular.js
参考文章:
http://www.alloyteam.com/2015/09/angularjs-study-of-dependency-injection/
http://www.cnblogs.com/xingyukun/archive/2007/10/20/931331.html
http://www.admin10000.com/document/6711.html
如果在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖。例如下面类 Human 中用到一个 Father 对象,我们就说类 Human 对类 Father 有一个依赖。
public class Human {
...
Father father;
...
public Human() {
father = new Father();
}
}
仔细看这段代码我们会发现存在一些问题:
(1). 如果现在要改变 father 生成方式,如需要用new Father(String name)初始化 father,需要修改 Human 代码;
(2). 如果想测试不同 Father 对象对 Human 的影响很困难,因为 father 的初始化被写死在了 Human 的构造函数中;
(3). 如果new Father()过程非常缓慢,单测时我们希望用已经初始化好的 father 对象 Mock 掉这个过程也很困难。
上面将依赖在构造函数中直接初始化是一种 Hard init 方式,弊端在于两个类不够独立,不方便测试。我们还有另外一种 Init 方式,如下:
public class Human {
...
Father father;
...
public Human(Father father) {
this.father = father;
}
}
上面代码中,我们将 father 对象作为构造函数的一个参数传入。在调用 Human 的构造方法之前外部就已经初始化好了 Father 对象。像这种非自己主动初始化依赖,而通过外部来传入依赖的方式,我们就称为依赖注入。
现在我们发现上面 1 中存在的两个问题都很好解决了,简单的说依赖注入主要有两个好处:
(1). 解耦,将依赖之间解耦。
(2). 因为已经解耦,所以方便做单元测试,尤其是 Mock 测试。
依赖注入有一个很大的特点:程序运行阶段才产生依赖关系,在编译阶段并不产生这个关系。降低程序间的耦合度。
为了理解angularJS中的依赖注入,我们先来尝试一下没有明确使用angularJS的前提下,我们如何来模仿依赖注入。
首先,我们要有一个注入器,里面必须包含注册函数与resolve函数。
var inject = {
dependencies : {},
register : function(key, value){
this.dependencies[key] = value;
},
resolve : function(deps, func, scope){
var arr = [];
for(var i = 0; i<deps.length; i++){
if(this.dependencies.hasOwnProperty(deps[i])){
arr.push(this.dependencies[deps[i]]);
}
}
console.log(arr);
return function(){
func.apply(scope || {}, arr);
}
}
};
思路很简单,注册的时候通过map容器来存放《名字, 真正功能》之间的关联,然后在resolve的时候通过function.apply()将函数的参数与真正功能关联起来。
inject.register("$http", {"get": function(){console.log("get")}});
inject.register("scope",{"test": " 111"});
var MyController = function($http, $scope){
$scope.test = 1;
$http.get();
}
MyController = inject.resolve(["$http", "scope"], MyController);
//此时MyController中的参数一$http 对应的就是 {"get": function(){console.log("get")}}
//参数二$scope 对应的就是{"test": " 111"}
MyController();
这大概就是其具体原理了。但是值得注意的是,上面的程序中如果参数调换顺序的话,那么是无法正常运行的。如果想要了解如何修改程序可以让其参数调换顺序不受影响,可以参考angularJS的源代码。那么在使用angularJS的情况下,
依赖注入的类型包括:依赖module、 依赖service。
依赖module的注入直接在module创建的时候就可以注入,只不过需要在HTML页面中加载所依赖module的源文件。举个例子:
//index.js文件
angular.module("dataRegistry", ["ngTable"]);
//对应HTML文件
<head>
...
<script src="../ng-table.js"></script>
</head>
假设依赖module特别多的话,这个时候需要使用bower来进行依赖module的管理。此处引进了bower。即使如此,bower能够自动下载所需要的module,但还是不能够自动加载到HTML页面中,这时,还是需要gulp来帮忙。这也就是gulp的概念了。我们的项目里面,gulp中通过设置gulpfile.js:
var options = {
src:"src",
dist:"dist",
tmp:"tmp",
e2e:"e2e",
wiredep:{
directory: "bower_components",
exclude: [/bootstrap-sass-official\/.*\.js/, /bootstrap\.css/]
}
};
其中,wiredep模块的作用就是自动化加载依赖module到HTML页面中。
前面已经大致讲解了依赖注入的原理,那么我们现在可以来看看,angularJS中内置的service有哪些?各自功能是什么?
$timeout
: 对应了 JS window.setTimeout 函数。可直接使用$timeout(function(){}, 1000);
$interval
: 对应了 JS window.setInterval 函数。可直接使用$interval(function(){}, 1000);
$http
: 服务向服务器发送请求,应用响应服务器传送过来的数据。用法演示: $http.get("welcome.htm").then(...);
更多关于$http
的用法,可以参考网页:
$location
: 返回当前页面的 URL 地址。用法演示:$location.absUrl();
$rootScope
:rootscope是各个controller中scope的桥梁。用rootscope定义的值,可以在各个controller中使用(在所有controller里面都是可以直接用{{$root.xxx}}来显示)。
$scope
: 数据绑定作用。html和单个controller之间的桥梁。
$modal
: 该service只有一个方法open()
用于创建对话框。
$modalInstance
: 扩展了两个方法close(result)
、dismiss(reason)
,这些方法很容易关闭窗口并且不需要额外的控制器。
$animate
: $animate服务提供了基本的DOM操作功能如在DOM里插入、移除和移动元素,以及添加和删除类。这个服务是ngAnimate的核心服务,为CSS和Javascript提供了高档次的动画。 更多的可以查看:http://www.lai18.com/content/5636288.html
$parse
: 将angularJS表达式转换为函数。更多网址参考:https://docs.angularjs.org/api/ng/service/$parse http://www.cnblogs.com/ys-ys/p/4989682.html
$interpolate
: http://www.cnblogs.com/ys-ys/p/4989682.html
$locale
:provides localization rules for various Angular components
$state
: 通常是在ng-route与ui-route上作为路由的跳转使用,常用方法就是路由跳转方法$state.go()
.
$q
: angular中的Promise对象。可以参考网址http://www.111cn.net/wy/js-ajax/71384.htm
$cacheFactory
: 创建缓存的工厂,通过构造缓存实例,就可以直接使用。https://docs.angularjs.org/api/ng/service/$cacheFactory
$window
: 代替客户端使用的window类。由于window在JavaScript中是全局变量,容易引发误解。所以使用这个来替代。
当然,我们也可以自己创建依赖service,请查看这里:https://www.zybuluo.com/frank-shaw/note/509468