Angularjs 如何在角度指令之间进行有效沟通?

Angularjs 如何在角度指令之间进行有效沟通?,angularjs,Angularjs,我遇到了我的应用程序所需的冗余逻辑,我希望将其转换为一种指令形式,在这种形式下,我不会将控制器作用域与视图属性进行卷积。这个想法很简单。我想要两个指令(一个父元素和一个子元素),具有1对多关系(一个父元素有X个子元素) 该指令只是一个列表,用户可以在其中单击一个元素(子指令),并让该元素添加一个活动类,而所有其他同级元素都删除了活动类 控件基本上是一个单选按钮(功能相同),我只是想让它对任何类型的元素都通用。这就是我到目前为止所做的: app.directive('skSelect', func

我遇到了我的应用程序所需的冗余逻辑,我希望将其转换为一种指令形式,在这种形式下,我不会将控制器作用域与视图属性进行卷积。这个想法很简单。我想要两个指令(一个父元素和一个子元素),具有1对多关系(一个父元素有X个子元素)

该指令只是一个列表,用户可以在其中单击一个元素(子指令),并让该元素添加一个
活动
类,而所有其他同级元素都删除了
活动

控件基本上是一个单选按钮(功能相同),我只是想让它对任何类型的元素都通用。这就是我到目前为止所做的:

app.directive('skSelect', function(){
    return {
        restrict:'A',
        controller: function($scope){
            this.reset = function(){
               //HERE I WANT TO SET ALL CHILDREN sk-select-item DIRECTIVES TO isSelected = false SOMEHOW
            }
        },
        link: function(scope, element, attrs){

        }
    }
});

app.directive('skSelectItem', function(){
    return {
        restrict:'A',
        require:'^skSelect',
        replace:false,
        template:'<div ng-class="{active: isSelected}" ng-click="select()"></div>',
        link:function(scope, element, attrs, ctrl){

            scope.isSelected = false;


            //scope.$watch('isSelected', function(isSelected){
            //    if(isSelected){
            //        element.addClass('active');
            //    }else{
            //        element.removeClass('active');
            //    }
            //});

            scope.select = function(){
                ctrl.reset();
                scope.isSelected = true;
            }




        }
    }
});
app.directive('skSelect',function(){
返回{
限制:'A',
控制器:功能($scope){
this.reset=函数(){
//在这里,我想将所有子项sk select item指令设置为isSelected=false
}
},
链接:函数(范围、元素、属性){
}
}
});
app.directive('skSelectItem',function(){
返回{
限制:'A',
要求:“^skSelect”,
替换:false,
模板:“”,
链接:函数(范围、元素、属性、ctrl){
scope.isSelected=false;
//范围:$watch('isSelected',函数(isSelected){
//如果(当选){
//元素addClass('active');
//}其他{
//元素。removeClass(“活动”);
//    }
//});
scope.select=函数(){
ctrl.reset();
scope.isSelected=true;
}
}
}
});

因此,我的问题在于尝试使用一个
reset()
函数,在该函数中,父对象需要与子对象通信,以将其isSelected属性设置为
false
。我也不确定是否应该在
skSelectItem
指令中使用
模板
,以添加/删除
活动的
类并绑定单击事件,或者是否应该只使用
元素。on('click')
范围。$watch('isSelected',…)
为了实现这一点?

有几种方法可以处理两个指令之间的通信。下面是两个很好的示例,说明如何实现这一点

一般关注事项 在指令定义上,如果您使用的是类似于
的模板,则必须将scope属性指定为true,才能为。否则,您将在父作用域上共享该变量

使用$broadcast$on 在这种情况下,父指令可以发送一个事件来通知子指令某些内容发生了更改

在代码中:

// on the parent directive.
this.reset = function() {                                    
     $scope.$broadcast('skSelect::reset');
}

//on the child directive. remember to set the scope to true.

link:function(scope, element, attrs, ctrl){

                    scope.$on('skSelect::reset', function (event) {
                        scope.isSelected = false;
                    });
这是标准的解决方案,但在使用相同类型的嵌套指令时会出现一些问题。由于无法停止emit事件,因此父级上的am事件抛出由所有子指令侦听

要解决这个问题,您应该生成一个随机键,用于事件的名称

        function buildEventName (key) {
          return 'skSelect::reset' + key;
        }

// parent controller 

controller: function($scope){

                    this.eventKey = Math.random() * 999999; // random key here.

                    this.reset = function() {
                        $scope.$emit(buildEventName(this.eventKey));
                    }
                },
//子链接函数

link:function(scope, element, attrs, ctrl){

                        scope.$on(buildEventName(ctrl.eventKey), function (event) {
                            scope.isSelected = false;
                        });
在父控制器上保存子作用域
您应该尝试使用scope.$emit,并将子指令订阅到s向父级抛出的事件。我将在一分钟后发布一个答案。好的,让父$emit一个事件,让子$emit一个事件,并在事件发生时设置
isSelected=false
?对我来说这听起来很可靠。使用模板怎么样?我想能够在我正在写的任何类型的元素上使用它,给我一分钟。好的,这是有意义的。非常感谢。顺便说一句,我认为我们需要使用
$scope.$broadcast()
而不是
$scope.$emit()
,以便向下传播事件(父级->子级)。除此之外,它工作得很好!
// parent controller

controller: function($scope){
                    var childs = [];

                    this.reset = function() {
                        angular.forEach(childs, function  (child) {
                            child.clear();
                        });                            
                    };

                    this.addChild = function (childScope) {
                        childs.push(childScope);
                    };
                },

// child link function

link:function(scope, element, attrs, ctrl){

                    ctrl.addChild(scope);

                    scope.clear = function () {
                        scope.isSelected = false;
                    };                     

                    scope.select = function(){
                        ctrl.reset();
                        scope.isSelected = true;
                    };
                }