根据AngularJS属性的指令装饰服务 [英] Decorate Service in Directive based on Attributes in AngularJS
问题描述
披露:我是新来的角,所以如果我这样做,出现奇怪的或完全错误的东西,随时指出这一点。
Disclosure: I'm new to angular, so if I'm doing something that appears strange or just plain wrong, feel free to point that out.
我有一个指令 vpMap
,我想用这样的:
I have a directive vpMap
that I want to use like this:
<div my-map with-tile-layers with-geolocator></div>
我有我想要有条件装修地图
服务的基础上,指令以开头的属性与
I have a Map
service that I want to decorate conditionally, based on the attributes of the directive that begin with with
这看起来是这样的:
angular.module('myApp.map',[])
.service('Map',someServiceFunction)
.directive('myMap',['Map','$provide',function(Map,$provide) {
return {
controller: function($scope,$element,$attrs) {
angular.forEach($attrs,function(val,key) {
if(key.match(/^with/)) {
switch(key) {
case 'withTileLayers':
$provide.decorator(Map,someDecoratorFunction);
break;
}
}
});
}
};
}]);
这是在这一点上,我发现我无法访问$在我的指令提供服务,虽然我不知道为什么。根据该文件你可以注入任何东西到指令和,我以为$提供像$ HTTP
It's at this point that I discover I can't access the $provide service in my directive, although I'm not sure why. According to the documentation you can inject anything into directives and, I thought $provide was one of those global angular services like $http
这是不好的架构?什么规则我是不理解?
Is this bad architecture? What rules am I not understanding?
推荐答案
供应商是为了通过在配置阶段的 $注射器
中。
Providers are meant to be used by the $injector
in the configuration phase.
从供应商指南:
在配置阶段已经结束,与供应商互动
不允许并创建服务的过程开始。我们称之为
应用程序生命周期的一部分运行阶段。
Once the configuration phase is over, interaction with providers is disallowed and the process of creating services starts. We call this part of the application life-cycle the run phase.
所以,你将不得不使用配置块用来装饰。
So you would have to use the config block for decorating.
要装饰一个服务的条件的,你可以使用装饰的功能,里面的一些predicate,沿着这(未测试)线的东西:
To decorate a service conditionally, you may use some predicate inside the decorator's function, something along the lines of this (not tested):
// define a predicate that checks if an object starts with a key
function keyInObject(obj, key) {
var propKeys = Object.keys(obj),
index = propKeys && propKeys.length || 0;
while (index--) {
if (propKeys[index].indexOf(key) === 0) {
return true;
}
}
return false;
}
app.config(function($provide) {
// uhmm, decorate
$provide.decorator('Map', function($delegate) {
var service = $delegate;
// only extend the service if the predicate fulfills
keyInObject(service, 'with') && angular.extend(service, {
// whatever, man
});
return $delegate;
});
});
然而,即使这样也不能帮助我们的,因为我们需要得到在链接阶段的,其售后服务是非常被注射的键(和饰)。
However, even this won't help us, as we need to get the keys in the linking phase, which is well after the service have been injected (and decorated).
要确保你完全了解这里的装饰的意义;我们使用装饰永久性地改变对象(服务)结构。的装饰,是指对象的元数据,而不是其状态的
To make sure you fully understand the meaning of decoration here; we use decoration to permanently alter the object (the service) structure. Decoration refers to the object's meta data, not its state.
鉴于上述情况,最好的选择是简单地创建一个服务的所有必需的功能,并完全放弃装饰。后来,虽然里面的链接
则可以使用迭代来决定调用哪个方法,例如:
Given the above, the best choice would be to simply create a service with all the required functionality, and abandon decoration altogether. Later, while inside link
you can use the iteration to decide which of the methods to call, e.g.:
// I took the liberty of switching the positions of key/val arguments
// for semantics sake...
angular.forEach($attrs, function(key, val) {
if (val.match(/^with/)) {
switch (val) {
case 'withTileLayers':
Map.useTileLayers(); // use specific API in the service
break;
}
}
});
这篇关于根据AngularJS属性的指令装饰服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!