Angular学习(十三)——组织模块依赖

      在之前的学习中我们已经看到控制器是如何给我们空间用于存放暴露正确的数据和函数给视图层模板的代码。但是如果还需要其他代码来支持我们的应用,那我们该如何处理?能够容纳这个最明显的地方就是控制器中的函数。

     在一个小应用中,我们可以将所有的代码放到控制器中。但是在真实的应用中很快变得难以管理,控制器中存放的代码太多,以至于后期很难理解,也很难去维护。这里我们可是介绍模块,它为应用中的函数域提供了一中组织管理依赖的方法,是一种自动解决依赖的机制(也被称为依赖注入)。大体上说,我们称这些为依赖服务,因为他们给应用提供了指定的服务。

     例如,如果我们的购物网站里一个控制器需要从服务器端查询一份销售表,我们想利用一些对象,暂时成为items,用来处理从服务器端查询列表。items对象依次需要一些通过XHR或WebSockets的方法和服务器上的数据进行交互。

    不利用模块的做法类似于:


    虽然这种方式可以运行,但是存在一些潜在的问题:
1、如果其他控制器也需要从服务器中获取items,现在就不得不从新拷贝一份代码。这将使的代码维护成为中负担,假如我们重新做了架构或其他变更,我们不得不去更新耕读地方的代码。
2、由于其他因素,比如服务器端认证,解析的复杂度等等,所以很难说清这个控制器对象的职责范文,同时使得代码的阅读性变的很差。
3、为了测试这部分代码,实际上我们需要一台运行的服务器,或者能够用动态的方法monkey patch模拟XMLHttpRequest返回模拟数据。不得不运行服务器来进行测试,这使得测试工作非常缓慢,同时也给测试环节带来了片状问题。这个monkey patch路由解决了速度和片状问题,但是意味着你不得不记住未打补丁和已打补丁的对象,在测试用例时,这个给测试带来了额外复杂度,以及强制你指定需要的线上数据格式(只要这个测试变化,就不得不更新测试用例)。
     使用模块,和从他们那边获取的依赖注入,我们可以写我们的控制器更简单,类似于这样:
function ShoppingController($scope,items)
{
     $scope.items = items.query();
}

    此时,代码看上去很酷,但是我们可能会问“items从哪里来?”。上面的代码假设我们已经定义了items作为一服务。服务是单实例的(单实例)对象,能够执行必要的任务以及支持应用的功能。Angular自带了很多服务,例如用于和浏览器地址进行交互的$location,用户随URL变化切换视图的$route,以及和服务器交互的$http.
     你应该能够创建自己的服务,用于为应用处理所欲特殊的任务。服务可以扩应用共享,如果需要他们。因此,当你需要跨控制器交互和分享状态,他们是一个很好的机制。Angular捆绑的服务都以$开头,因此,虽然你可以按照你喜欢的来命名,但是避免使用$开头从而避免命名冲突。
      你可以使用模块对象的API来定义服务。这里有三种函数用于创建不同层次复杂度和能力的通用服务:
1、provide(name, Object OR constructor()):一个可配置的、有复杂逻辑的服务。如果你传递了一个函数,那么它应该有一个叫$get       的函数返回这个服务的实例。否则的话Angular假设你已经产生了一个构造函数,当被调用时,创建这个实例。
2、factory(name, $getFunction()):一个不可配置的、有复杂逻辑的服务。你指定一个函数,当被调用时,返回服务实例。你可以认         为是provider(name, {$get:$getFunction()})
3、service(name, constructor()):一个不可配置、简单逻辑的服务,有点类似于带构造函数的provider,Angular调用它来创建服务实       例。

       于是,此时我们可以采用factory()的方式来对之前的items进行处理,我们可以像这样写服务:
//Create a module to support our shopping views
var shoppingModule = angular.module('shoppingModule',[]);

//Set up the service factory to create our items interface to 
//service-side database 
shoppingModule.factory('items',function(){
	var items = {};
	items.query = function(){
		//in real apps, we'd pull this data from the server 
		return [
			{title:"Paint pots",description:"Pots full of paint",price:3.95},
			{title:"Polka dots",description:"Dots with polka",price:2.95},
			{title:"Pebbles",description:"Just little rocks",price:6.95},
		];
	};
	return items;
});
        当Angular创建ShoppingController时,它将传递$scope和创建我们定义的items服务。这个是通过参数名匹配来完成的,也就是说,Angular看到ShoppingController雷的函数签名,就意识到它需要一个items对象,由于我们已经定义了一个items服务,它直接从这里取即可。
        查找这些字符串依赖的结果意味着向控制器构造函数注意功能参数是与顺序无关的。因此不是这样的形式:
function ShoppingController($scope, items){ ……}
        我们可以写成这样:
function ShoppingController(items, $scope){ ……}
         正如我们所预料的,它仍然能够运行。
         为了能和我们的模板一起运行,我们需要用ng-app标识符来标注模块名,就像这样:
<html ng-app="ShoppingModule">
         完成这个示例,我们实现了模板的完整代码如下:
<html ng-app="ShoppingModule">
<body ng-controller="shoppingController">
<h1>Shop!</h1>
<table>
	<tr ng-repeat="item in items">
		<td>{{item.title}}</td>
		<td>{{item.description}}</td>
		<td>{{item.price | currency}}</td>
	</tr>
	
</table>
</body>
<script src="angular.min.js"></script>
<script>
function shoppingController($scope,Items)
{
	$scope.items = Items.query();
}
//Create a module to support our shopping views
var shoppingModule = angular.module('ShoppingModule',[]);
//Set up the service factory to create our items interface to 
//service-side database 
shoppingModule.factory('Items',function(){
	var items = {};
	items.query = function(){
		//in real apps, we'd pull this data from the server 
		return [
			{title:"Paint pots",description:"Pots full of paint",price:3.95},
			{title:"Polka dots",description:"Dots with polka",price:2.95},
			{title:"Pebbles",description:"Just little rocks",price:6.95},
		];
	};
	return items;
});
</script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值