Angular框架提供了强大的依赖注入机制,这一切都是有注入器(injector)完成. 注入器会自动实例化服务组件和符合Angular API规则的特殊对象,例如控制器,指令,过滤器动画等。
那注入器怎么知道如何去创建这些特殊的对象呢? Angular提供了5种方式让注入器创建对象,其中最基础的方式就是提供者(provider), 其余四种方式(Value, Factory, Service, Constant)都是基于Provider的语法糖。一个模块(module)就是一种配置注入器实例工厂的方式,我们也称为提供者(provider)。当Angular应用从一个模块开始启动时,Angular会为该模块创建注入器,注册在该模块以及所依赖的模块中定义的提供者,注入器会用提供者来创建app的对象。
让我们通过如下几个例子来进一步了解上述五种方式的用法:
例一: Value
var myApp = angular.module('myApp', []); myApp.value('clientId', 'a12345654321x');
myApp.controller('DemoController', ['clientId', function DemoController(clientId) { this.clientId = clientId; }]);
<html ng-app="myApp"> <body ng-controller="DemoController as demo"> Client ID: {{demo.clientId}} </body> </html>
在myApp模块中通过Value的方式定义了clientId值, 在后面的代码中就可以通过注入的方式在控制器中注入clientId的值。
例二:Factory
Value的方式有其局限性,只适合定义简单类型, 工厂方式则有更多的灵活性:
- 可以注入使用其他服务
- 服务初始化
- 惰性初始化
工厂方法返回service实例,注意Angular的服务是单例的。 让我们看如下代码:
myApp.factory('apiToken', ['clientId', function apiTokenFactory(clientId) { var encrypt = function(data1, data2) { // NSA-proof encryption algorithm: return (data1 + ':' + data2).toUpperCase(); }; var secret = window.localStorage.getItem('myApp.secret'); var apiToken = encrypt(clientId, secret); return apiToken; }]);
我们通过工厂方法返回了一个加密过的token, 在第二个参数中我们注入了例一中的clientId.
例三:Service
在面向对象过程中我们通常使用自定义类型。该例中我们定义了UnicornLauncher构造方法,并通过service方法实例化unicornLauncher:
function UnicornLauncher(apiToken) { this.launchedCount = 0; this.launch = function() { // Make a request to the remote API and include the apiToken ... this.launchedCount++; } } myApp.service('unicornLauncher', ["apiToken", UnicornLauncher]);
例四: 提供者
提供者(Provider)为构造Angular应用的组件对象提供了最强大的支持。从语法层面讲Provider是$get方法的具体实现,是一个工厂方法类似例二的Factory. 对于构造service组件,使用上例中的Service方法就可以了,如果我们想给组件加上更多的启动配置项,增加组件的重用性,则考虑使用provider. 基于上面的例子我们给UnicornLauncher添加了“useTinfoilShielding”配置项:
myApp.provider('unicornLauncher', function UnicornLauncherProvider() { var useTinfoilShielding = false; this.useTinfoilShielding = function(value) { useTinfoilShielding = !!value; }; this.$get = ["apiToken", function unicornLauncherFactory(apiToken) { // let's assume that the UnicornLauncher constructor was also changed to // accept and use the useTinfoilShielding argument return new UnicornLauncher(apiToken, useTinfoilShielding); }]; }); myApp.config(["unicornLauncherProvider", function(unicornLauncherProvider) { unicornLauncherProvider.useTinfoilShielding(true); }]);
通过provider api,定义了UnicornLauncherProvider,其中$get方法中定义了实例化UnicornLauncher的工厂方法,实例化方法参数中包含了useTinfoilShielding参数,该值由myApp.config配置。即Angular通过UnicornLauncherProvider实例化UnicornLauncher service. 注意在config方法中通常只能注入Provider,在应用启动时,Angular首先会配置并实例化所有的Provider实例,然后根据Provider来创建其他组件,在config阶段,service还未被实例化,所以不能在config方法中访问service组件。在config阶段结束后便进入run阶段,就不能再访问provider了,angular会根据provider的定义来初始化组件。
例五:常量(Constant)
上述例子中可见Angular应用启动分为两个阶段: config和run. 在config阶段services是不可用的,也不能访问通过Value初始的值类。 对于应用级别的常量,在config和run阶段皆可见,我们可以通过Constant来定义,参考如下示例代码:
myApp.constant('planetName', 'Greasy Giant'); myApp.config(['unicornLauncherProvider', 'planetName', function(unicornLauncherProvider, planetName) { unicornLauncherProvider.useTinfoilShielding(true); unicornLauncherProvider.stampText(planetName); }]); myApp.controller('DemoController', ["clientId", "planetName", function DemoController(clientId, planetName) { this.clientId = clientId; this.planetName = planetName; }]);
我们定义了planetName常量,在config和controller中都可以访问。
<html ng-app="myApp"> <body ng-controller="DemoController as demo"> Client ID: {{demo.clientId}} <br> Planet Name: {{demo.planetName}} </body> </html>
特殊组件
前文中我们提到过,除了service组件,我们可以实现一些特殊组件,例如控制器,指令,过滤器和动画。这些组件可作为Angular框架的插件,实现了Angular框架特定的接口。这些接口也是基于Factory的。让我来看下面的一些例子:
myApp.directive('myPlanet', ['planetName', function myPlanetDirectiveFactory(planetName) { // directive definition object return { restrict: 'E', scope: {}, link: function($scope, $element) { $element.text('Planet: ' + planetName); } } }]);
<html ng-app="myApp"> <body> <my-planet></my-planet> </body> </html>
上面例子中,我们通过directive来注册了myPlanet组件,和Factory一样,定义了myPlanetDirectiveFactory工厂方法,返回一个指令对象。同样我们也可通过工厂方法自定义指令和动画。
相当于其他类型的组件,控制器没有使用工厂方法,而是构造器,因而控制器不是单例的。
myApp.controller('DemoController', ['clientId', function DemoController(clientId) { this.clientId = clientId; }]);
让我们总结一些上面例子中的要点:
- 注入器会通过提供者创建两种类型的组件: 服务组件(services)和特殊组件(controllers, directives, filters, animations).
- Angular框架提供了5类提供者来创建对象: Value, Factory, Provider, Constant 和 Service, 其中Provider是最基础也是最强大的,另外四种都是基于Provider的封装。
- Factory和Service是最常用的, 两者的区别是Service方法只返回某类型的对象,而Factory支持Javascript原始类型和函数。
- Provider的用法相对复杂,除非需要为可重用组件提供全局的配置项,我们一般考虑使用其他的方式来构建组件。
- 除了控制器使用构造器,其余特殊组件都使用工厂方式,控制器可以有多个实例,而其余特殊组件都是单例的。
具体总结可参考如下表格(摘自官方文档):
can have dependencies | yes | yes | no | no | yes |
uses type friendly injection | no | yes | yes* | yes* | no |
object available in config phase | no | no | no | yes | yes** |
can create functions | yes | yes | yes | yes | yes |
can create primitives | yes | no | yes | yes | yes |
相关推荐
NULL 博文链接:https://boyitech.iteye.com/blog/2167272
耶鲁大学的公开课提供了深入学习博弈论的机会,使学生能够理解并应用这一理论解决实际问题。 讲义中可能涵盖了以下几个关键知识点: 1. **基本概念**:博弈论的基本元素包括参与者(玩家)、策略集、支付函数和...
论文研究-不确定性下多目标博弈中弱Pareto-NS均衡的存在性.pdf, 在已知不确定参数变化范围的假设下, 研究了多目标博弈中弱Pareto-NS均衡点的存在性问题. 首先结合非合作...
未来,博弈论将继续在理论创新和实际应用中扮演重要角色,为解决现实世界中的决策问题提供有力工具。 总之,博弈论是一门深奥且实用的学科,它教会我们在面对冲突和合作时,如何通过理性分析和策略制定,达到个体或...
哈佛大学的博弈论讲义是这个领域的权威资料之一,深受学者和学生们的喜爱。本讲义深入浅出地介绍了博弈论的基本概念、理论与应用,帮助读者理解在竞争与合作中的决策制定。 首先,我们要理解博弈论的核心概念——...
1. **完全信息静态博弈** - 这是博弈论的基础,主要探讨在所有参与者都知道所有信息的情况下,如何达到纳什均衡,即每个参与者在考虑其他人的策略后,无法通过改变自己的策略来提高收益。 2. **完全信息动态博弈** ...
综上所述,这组讲义提供了博弈论与信息经济学的全面介绍,涵盖了从基础的纳什均衡到更复杂的不完全信息博弈和信息经济学理论,对于理解个体在不确定环境下的决策行为具有重要意义。学习这些内容不仅有助于深入理解...
微观经济学讲义-第13章博弈论
综上所述,这份讲义全面覆盖了博弈论和信息经济学的基础理论,结合实际案例帮助学习者深入理解这些概念,对于经济学、管理学以及相关专业的学生和研究人员具有很高的学习价值。通过掌握这些知识,读者能够更好地分析...
七所大学的博弈论讲义,包括哈佛大学.卡内基梅隆大学.芝加哥大学.加利福尼亚大学(圣. 迭戈校区).加利福尼亚
快递物流行业义乌快递调研实录:产业集聚、利益博弈与价格战事-0725-国金证券-16页.pdf
势博弈与时变Log-linear分布式拓扑控制算法 势博弈与时变Log-linear分布式拓扑控制算法是为了解决UWSNs(Underwater Wireless Sensor Networks,水下无线传感器网络)中网络拓扑控制不稳定、频繁变化引起的网络能耗...
计算博弈第二讲-V61 计算博弈是自动化研究所 University of Chinese of Academy of Sciences 的一门专业普及课,旨在让学生理解博弈的基本概念、方法和应用。第二讲的主要内容是博弈表示方法、常见博弈类型和博弈的...
2019年2季度大类资产配置报告:从基本面博弈转向资金面博弈-华泰证券-20190424.pdf
本讲义涵盖的内容广泛,包括了非合作博弈理论、完全信息与不完全信息博弈,以及信息经济学中的委托-代理理论和信号传递机制。 首先,非合作博弈理论是博弈论的基础,它假设参与者无法通过协议或合作改变博弈结果。...
首先,非合作博弈理论是博弈论的基础,它描述了两个或多个独立决策者之间的互动,这些决策者无法通过正式协议来协调行动。在完全信息静态博弈中,所有参与者都对游戏规则和对手的策略有完全了解。纳什均衡是这种博弈...
在本讲义中,我们将探讨非合作博弈理论和信息经济学的相关概念。 首先,非合作博弈理论是博弈论的核心,主要关注参与者在没有共同利益或协议约束下的决策过程。在完全信息静态博弈中,所有参与者都掌握所有相关信息...
快递物流行业义乌快递调研实录:产业集聚、利益博弈与价格战事-20190725-国金证券-16页.pdf
人机博弈。PDF中文版。。。。。。。。。。。。。。。。。。。。。。。。。