披露:我是棱角分明的新人,所以如果我做一些看似奇怪或完全错误的事情,请随意指出。
我有一个我想要使用的指令vpMap
:
<div my-map with-tile-layers with-geolocator></div>
根据以Map
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;
}
}
});
}
};
}]);
此时我发现我无法在我的指令中访问$ offer服务,尽管我不确定原因。根据文档,您可以将任何内容注入指令中,我认为$ provide是其中一种全局角度服务,如$ http
这是糟糕的架构吗?我不理解什么规则?
答案 0 :(得分:2)
供应商应在配置阶段由$injector
使用。
配置阶段结束后,与提供商的互动就是 禁止并开始创建服务的过程。我们称之为 应用程序生命周期的一部分运行阶段。
所以你必须使用配置块进行装饰。
要有条件地装饰服务 ,您可以在装饰器的功能中使用一些谓词,这与此类似(未经测试):
// 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;
});
});
但是,即使这样也无法帮助我们,因为我们需要在链接阶段中获取密钥,这在服务注入后很久(和装饰)。
确保你完全明白装饰的含义;我们使用装饰永久地改变对象(服务)结构。 装饰是指对象的元数据,而不是其状态。
鉴于上述情况,最好的选择是简单地创建具有所有必需功能的服务,并完全放弃装饰。稍后,在link
内,您可以使用迭代来决定调用哪种方法,例如:
// 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;
}
}
});