简体   繁体   English

AngularJS指令到指令通信

[英]AngularJS Directive to directive communication

I've a directive nested within another directive as in the below fiddle. 我有一个嵌套在另一个指令中的指令,如下面的小提琴所示。

http://jsfiddle.net/sriramr/T7W6T/3/ http://jsfiddle.net/sriramr/T7W6T/3/

My question is: if a variable in the parent directive changes value, how to automatically update the value of a variable in the child directive which is computed from the parent variable? 我的问题是:如果父指令中的变量更改了值,如何自动更新从父变量计算出的子指令中变量的值?

var myapp = angular.module('myApp',[]);
myapp.directive('parentDir', parentDir);
    function parentDir() {
        return {
            restrict:'E',
            controller: function eCtrl($scope) {
                $scope.parVal = 100;
                $scope.$on("event",function(e,data) {
                    console.log("emit")
                    $scope.parVal = 200;
                })

            },
            template:'<div><first-dir></first-dir</div>'
        }
    }

myapp.directive('firstDir', firstDir);
function firstDir() {
    return {
        restrict:'E',
        controller: function($scope) {
            //$scope.$watch('parVal',function() {
                $scope.childVal = $scope.parVal + 1;
            //})
            $scope.changeVal = function() {
                $scope.$emit("event")
            }
        },
        template:'<div>first Dir: {{parVal}} {{childVal}} <br /> <button ng-click="changeVal()">Change</button></div>'
    }
}

The variable parVal from the parent directive's controller's scope gets handed down to the child directive's controller. 来自父指令的控制器范围的变量parVal被传递给子指令的控制器。 The child directive has its own variable childVal which is parVal + 1 . child指令具有其自己的变量childVal ,即parVal + 1 I try to change parVal 's value indirectly by emitting an event in the child directive. 我尝试通过在子指令中发出一个事件来间接更改parVal的值。 As expected, parVal 's value changes and is reflected in the View. 正如预期的那样, parVal的值会更改并反映在视图中。 However, childVal 's value is not changed. 但是, childVal的值不会更改。

I am able to see the updated value of childVal using a $watch on parVal . 我可以在childVal使用$ watch查看parVal的更新值。 Is there any other way I can do this? 我还有其他方法可以做到吗?

There are a few ways you can share code between these two directives. 您可以通过几种方式在这两个指令之间共享代码。

One way is to take advantage of how firstDir prototypically inherits from parentDir . 一种方法是利用firstDir原型继承自parentDir You're already doing that with parVal , but you probably had issues updating parVal from within the child directive. 您已经使用parVal进行了此parVal ,但是您可能在从child指令中更新parVal遇到了问题。 An easy workaround is to create an update function in the parent directive. 一个简单的解决方法是在父指令中创建一个更新函数。 This gives you access to update the scope directly. 这使您可以直接更新范围。 example: http://jsfiddle.net/T7W6T/4/ 示例: http//jsfiddle.net/T7W6T/4/
edit: I don't like the above approach because it tightly couples both directives and firstDir won't work on it's own. 编辑:我不喜欢上面的方法,因为它紧密地结合了两个指令,并且firstDir不能firstDir

Another way is to create a shared service. 另一种方法是创建共享服务。 A service in angular is a singleton, so anywhere it is injected into a controller will be the same instance as everywhere else. 角度服务是单例的,因此将其注入控制器中的任何地方都将与其他地方相同。 You can easily create a pub/sub mechanism. 您可以轻松创建发布/订阅机制。 Just be sure to clean up the subscribers when the scope of the subscriber is destroyed. 只需确保在破坏订户范围时清理订户。 This is my preferred way to share between directives and controllers because you don't pollute your scope. 这是我在指令和控制器之间共享的首选方式,因为您不会污染范围。 Remember, everything bound to scope has an effect on the digest. 请记住,与范围相关的所有内容都会影响摘要。

Example code of a minimal pub/sub mechanism: 最小发布/订阅机制的示例代码:

myapp.service('SharedService', function(){
    var listeners = [];
    return {
        publish: function(){
            angular.forEach(listeners, function(listener){
               listener.call(null); 
            });
        },
        subscribe: function(fn){
            listeners.push(fn);
        },
        unsubscribe: function(fn){
            var idx = listeners.indexOf(fn);
            if(idx > -1){
                 listeners.splice(idx,1);   
            }
        }
    }
});

You interact with this from the parent directive like so: 您可以通过父指令与此交互,如下所示:

            var update = function(){
                $scope.parVal = 200;
            };

            SharedService.subscribe(update);

            $scope.$on("$destroy", function(){
               SharedService.unsubscribe(update); 
            });

And the child directive is the only thing that can access the function to publish to listeners: 而且child指令是唯一可以访问该函数以发布给侦听器的东西:

        $scope.updateParVal = function(){
            SharedService.publish();
        };

http://jsfiddle.net/T7W6T/5/ http://jsfiddle.net/T7W6T/5/

There's a pretty good explanation on SO about whether scope inheritance or $emit is better: https://stackoverflow.com/a/18179640/151445 关于范围继承还是$emit更好,因此有一个很好的解释: https : //stackoverflow.com/a/18179640/151445

One thing I don't usually see mentioned about the service approach is that you control exactly where subscribers and publishers are bound. 关于服务方法,我通常不会看到的一件事是,您可以精确控制订户和发布者的绑定位置。 With $scope.$emit and $scope.$on , anyone with a scope can go crazy with events. 使用$scope.$emit$scope.$on ,任何具有范围的人都可以为事件疯狂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM