我有以下标记:
<div class="row" loader="loader" address-book>
<!-- Loading complete - this should show result -->
<div loader-success></div>
<!-- Loading failed - this should show some error -->
<div loader-failure>Failure</div>
</div>在这里,address-book是主要应用程序,而loader只在页面加载时作为动画显示。地址簿的内容将进入loader-success,失败消息(即,如果没有找到内容)将进入loader-failure。
因此,我的想法是使用以下指令:
app.directive('loader', function($compile, $timeout)
{
return {
restrict: 'AE',
scope: {
loader: '&'
},
transclude: true,
template:
'<div class="row" ng-if="loading">' +
' <div class="small-15 columns text-center">' +
' <i class="fa fa-spin fa-circle-o-notch"></i>' +
' </div>' +
'</div>' +
'<div ng-transclude></div>',
link: function(scope, element, attrs)
{
scope.loading = true;
scope.failure = false;
scope.success = false;
scope.$watch('loader', function(fn) {
if (_.isFunction(fn)) {
scope.loader()
.then(function(){
scope.success = true;
scope.loading = false;
scope.$safeApply();
})
.catch(function() {
scope.failure = true;
scope.loading = false;
scope.$safeApply();
});
}
});
}
};
}); 其中scope.loader是来自address-book的$q集的承诺。在地址簿试图获取内容后,承诺就会被解决/拒绝。
对于成功/失败的块,我有:
app.directive('loaderFailure', function()
{
return {
restrict: 'AE',
link: function(scope, element, attrs)
{
element.hide();
scope.$watch('failure', function(value) {
if (_.isTrue(value)) {
element.show();
}
});
}
};
});
app.directive('loaderSuccess', function()
{
return {
restrict: 'AE',
link: function(scope, element, attrs)
{
element.hide();
scope.$watch('success', function(value) {
if (_.isTrue(value)) {
element.show();
}
});
}
};
});然而,由于loader上的隔离作用域,loader-success和loader-failure两个孩子的作用域不能再读取父程序的作用域,我不能在loader上使用$compile,因为那样会将作用域从通讯簿的应用程序中删除。
我能做什么?
发布于 2014-09-26 21:09:25
你可以利用事件。如果您希望从子节点发送一些日期给父级,请使用$scope.$emit。
从父母到孩子,$scope.$broadcast -可能会产生负面的性能影响。
当您希望在松散耦合的组件之间进行通信时,使用事件是一种很好的方法。
请参阅有关事件的更多信息:
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit
发布于 2014-09-26 21:40:08
所以我最终使用了$emit。但是,由于我的loader指令可以在同一页上的多个不同组件上使用,因此能够区分这两个组件是很重要的。另外,将loader添加到一个元素中,并在其上运行另一个指令。
为了解决这些问题,我就是这样做的:
Failure 然后使用channel作为唯一标识符。它甚至可以是另一个指令作用域的$id,以确保它是完全唯一的。现在,这些指令如下:
app.directive('loader', function($compile, $rootScope)
{
return {
restrict: 'AE',
scope: {
loader: '&',
channel : '@loaderChannel'
},
transclude: true,
template:
'<div class="row" ng-if="loading">' +
' <div class="small-15 columns text-center loader">' +
' <i class="fa fa-spin fa-circle-o-notch"></i>' +
' </div>' +
'</div>' +
'<div ng-transclude></div>',
link: function(scope, element, attrs)
{
scope.loading = true;
scope.$watch('loader', function(fn) {
if (_.isFunction(fn)) {
scope.loader()
.then(function(){
scope.loading = false;
$rootScope.$emit('LOADER_SUCCESS', scope.channel);
scope.$safeApply();
})
.catch(function() {
scope.loading = false;
$rootScope.$emit('LOADER_FAILURE', scope.channel);
scope.$safeApply();
});
}
});
}
};
});
app.directive('loaderFailure', function($rootScope)
{
return {
restrict: 'AE',
link: function(scope, element, attrs)
{
element.hide();
$rootScope.$on('LOADER_FAILURE', function(event, channel) {
if (channel == attrs.loaderFailure) element.show();
});
}
};
});
app.directive('loaderSuccess', function($rootScope)
{
return {
restrict: 'AE',
link: function(scope, element, attrs)
{
element.hide();
$rootScope.$on('LOADER_SUCCESS', function(event, channel) {
if (channel == attrs.loaderSuccess) element.show();
});
}
};
});基本上,我$emit与频道的成功或失败。loader-success和loader-failure收听这些广播,匹配它们的频道,并相应地进行操作。
然后,在每个组件中,我只需定义scope.loader = $q.defer()并在需要时解析/拒绝它。
https://stackoverflow.com/questions/26067965
复制相似问题