首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >隔离父节点上的作用域防止与子节点的通信

隔离父节点上的作用域防止与子节点的通信
EN

Stack Overflow用户
提问于 2014-09-26 20:41:23
回答 2查看 94关注 0票数 2

我有以下标记:

代码语言:javascript
复制
<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

因此,我的想法是使用以下指令:

代码语言:javascript
复制
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集的承诺。在地址簿试图获取内容后,承诺就会被解决/拒绝。

对于成功/失败的块,我有:

代码语言:javascript
复制
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-successloader-failure两个孩子的作用域不能再读取父程序的作用域,我不能在loader上使用$compile,因为那样会将作用域从通讯簿的应用程序中删除。

我能做什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-09-26 21:09:25

你可以利用事件。如果您希望从子节点发送一些日期给父级,请使用$scope.$emit

从父母到孩子,$scope.$broadcast -可能会产生负面的性能影响。

当您希望在松散耦合的组件之间进行通信时,使用事件是一种很好的方法。

请参阅有关事件的更多信息:

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$emit

票数 2
EN

Stack Overflow用户

发布于 2014-09-26 21:40:08

所以我最终使用了$emit。但是,由于我的loader指令可以在同一页上的多个不同组件上使用,因此能够区分这两个组件是很重要的。另外,将loader添加到一个元素中,并在其上运行另一个指令。

为了解决这些问题,我就是这样做的:

代码语言:javascript
复制
                   Failure   

然后使用channel作为唯一标识符。它甚至可以是另一个指令作用域的$id,以确保它是完全唯一的。现在,这些指令如下:

代码语言:javascript
复制
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-successloader-failure收听这些广播,匹配它们的频道,并相应地进行操作。

然后,在每个组件中,我只需定义scope.loader = $q.defer()并在需要时解析/拒绝它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26067965

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档