让两个自定义指令在AngularJS中相互交互

Have two custom directives interact with each other in AngularJS

本文关键字:AngularJS 交互 指令 自定义 两个      更新时间:2023-09-26

我有两个指令

angular.module('myApp.directives', []).
            directive('exampleDirective', ['version', function(version) {
             return {
                      link:function(scope,elm,attr) {
                         elm.on('click',function() {
                              //access exampleDirective2 behaviour
                         });
                      }
                    }
            }]).
            directive('exampleDirective2', ['version', function(version) {
             return {
                      link:function(scope,elm,attr) {
                         elm.on('change',function() {
                              //access exampleDirective behaviour
                         });
                      }
                    }
            }]);

正如您在exampleDirective elm.on(click)函数上看到的,我想获得exampleDirective2函数,反之亦然。

在AngularJS中有办法实现这个吗?

这个问题有三个解决方案:

第一个解决方案:使用服务

在指令之间共享一个服务,该服务可以包含数据和函数。

.service('myService', function(){
    this.data = //....
    this.function = function() //...
})
.directive('dir1', ['myService', function(myService) {
   //...
   link: function(scope, elem, attrs) {
       scope.data = myService.data;
   }
}])

其他指令也一样。

第二个解决方案:指令的控制器

如果你的指令有父/子/兄弟关系:

.directive('dir1', function(){
    return {
        controller: function(scope, elem, attrs) {
            this.sayHello = function() {
                alert('hello')
            }
        }
    }
})
.directive('dir2', function(){
    return {
        require: '^dir1',
        link: function(scope, elem, attrs, dir1Ctrl) {
            dir1Ctrl.sayHello(); //will alert hello
        }
    }
})

然而,如果你的指令有独立的作用域,这将不起作用。此外,根据指令的关系(父/子或兄弟),require属性的sintax会略有变化;你可以在AngularJS的指令文档中找到更多信息。

第三种解决方案:使用events

你还可以从指令作用域发出/广播事件,或者注入$rootScope并将其用作事件总线:

.directive('dir1', function($rootScope){
    return {   
        link: function(scope, elem, attrs) {
           var emitEvent = function(){
               $rootScope.$emit('somethingHappenedEvent', { /*you can pass optional data*/ });
           }
           emitEvent();
       }
    }
})
.directive('dir2', function($rootScope) {
    return {
        link: function(scope, elem, attrs) {
            $rootScope.$on('somethingHappenedEvent', function(event) {
                if(!event.defaultPrevented) {
                    //react to event here
                }
            })      
        }
    }
})

您也可以使用正常的scope而不是$rootScope,但在这种情况下,您必须记住事件将在所有范围内向上/向下起泡(取决于使用$emit$broadcast)。我更喜欢$rootScope中的$emit,因为它将是唯一能够捕获事件的作用域,并且也将相当快。

这样做的一种方法是使用带有控制器的包装器指令,如果使用require,则可以在指令之间共享该指令。一个更简单、也许更好的解决方案(因为它不依赖于DOM)是使用一个公共服务来支持指令之间的通信。

如果你想在指令的方式这样做。这是答案

angular.module('myApp.directives', []).
        directive('exampleDirective', ['version', function(version) {
         return {
                  link:function(scope,elm,attr) {
                     elm.on('click',function() {
                          //access exampleDirective2 behaviour
                          scope.exampleDirective2Function();
                     });
                     scope.exampleDirectiveFunction = function (){
                          //write your code here
                     }
                  }
                }
        }]).
        directive('exampleDirective2', ['version', function(version) {
         return {
                  link:function(scope,elm,attr) {
                     elm.on('change',function() {
                          //access exampleDirective behaviour
                          scope.exampleDirectiveFunction();
                     });
                     scope.exampleDirective2Function= function (){
                          //write your code here
                     }
                  }
                }
        }]);
另一种方法是,你可以编写一个服务,在其中编写一个函数,然后通过向指令中注入service来使用该服务函数。