我有以下标记:
<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
是来自$q
的{{1}}集的承诺。在地址簿尝试获取内容后,承诺得到解决/拒绝。
对于我有的成功/失败块:
address-book
但是,由于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
上使用$compile
,因为这会将范围从地址簿的应用中删除。
我该怎么办?
答案 0 :(得分:2)
您可以使用活动。如果您想将儿童的某些日期发送给父母使用$scope.$emit
。
从父母与子女$scope.$broadcast
- 可能会产生负面影响
当您想要在松散耦合的组件之间进行通信时,使用事件是一种很好的方法。
查看有关活动的更多信息:
https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope#$发射
答案 1 :(得分:0)
所以我最终使用了$emit
。但是,由于我的loader
指令可以在同一页面上的多个不同组件上使用,因此能够区分这两者是很重要的。此外,loader
被添加到元素上,并在其上运行另一个指令。
要解决这些问题,我就这样做了:
失败然后将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()
并在需要时解析/拒绝它。