$scope.$emit/$broadcast 在 angular JS 中的自定义指令通信中不起作用

$scope.$emit/$broadcast not working in Custom Directive Communication in angular JS

我正在使用 HighCharts 来表示 堆积条形图 以及 折线图 。我的要求是 onClick 的堆积条形图 折线图应显示对应于 clicked.I 部分使用 $broadcast$on.当我在 highchart.js 中使用 $emit 时它不起作用,但是当我使用 $broadcast$scope.$parent.$broadcast 它有效。有人可以让我知道为什么事件的向上流动有效而向下无效。我的两个指令都指向同一个控制器。

在我的例子中,为什么单独使用 $scope.$emit$scope.$broadcast 不起作用?

index.html

    <div ng-controller='MainCtrl'>
      <chart values='basicAreaChart' id="container" technology="3G" url="../json/HighCharts.json"></chart>

      <linechart values='basicLineChart' id="container2" technology="LTE" click='clicked'></linechart>
    </div>

controller.js

  angular.module('chartsExample', ['lineChart','highchart']).controller('MainCtrl',
    [ '$scope', '$http', function($scope, $http) {
   } ]);

highchart.js

'use strict';

angular.module('highchart', []).directive('chart', function() {
return {
    restrict: 'E',
    scope: {
        chartData: "=values"
     },
    transclude: true,
    replace: true,
    controller:function($scope,$element,$attrs,$http){
        $http.get($attrs.url).success(function(data) {
            $scope.chartData = data;
            console.log('technology='+$attrs.technology+' '+$scope.a);
        });
    },
    link: function($scope, $element, $attrs,$rootScope) {
         '+$attrs.type);

        $scope.$watch('chartData', function(value) {
            if (!value){
                //console.log('In return');
                return;
            }
          // Initiate the chartData.chart if it doesn't exist yet
           $scope.chartData.chart = $scope.chartData.chart ;
            $scope.chartData.chart.renderTo =$attrs.id

            $scope.chartData.chart.events = {
                click : function() {
                    console.log('Chart clicked '+$scope.isClicked+' '+$scope.a);
                    $scope.click="false";

                    $scope.$parent.$broadcast('HIGH_CHART_CLICKED', 'clicked');
         //This works but $scope.$emit or $scope.$broadcast does'nt work???

                }
            };
            $scope.chartObj = new Highcharts.Chart($scope.chartData);
        },true);
    }
};
});

linechart.js

'use strict';

angular.module('highchart', []).directive('chart', function() {
return {
    restrict: 'E',
    scope: {
        linechartData : "=values"
     },
    transclude: true,
    replace: true,
    controller:function($scope,$element,$attrs,$http){
        $scope.$on('HIGH_CHART_CLICKED',function(e,data){
            console.log('Line chart Listening event');
            $http.get("../json/NewLineChart.json").success(function(data) {
                $scope.linechartData = data;
                console.log('this is from line chart');
            });
        });
    },
    link: function($scope, $element, $attrs,$rootScope) {
         '+$attrs.type);

        $scope.$watch('linechartData', function(value) {
            if (!value){
                //console.log('In return');
                return;
            }
          // Initiate the chartData.chart if it doesn't exist yet
           $scope.chartData.chart = $scope.chartData.chart ;
            $scope.chartData.chart.renderTo =$attrs.id
           }
            };
            $scope.chartObj = new Highcharts.Chart($scope.chartData);
        },true);
    }
};
});

好的。您有两个同名的指令(图表)。这个答案假设第二个实际上应该是 linechart

图表和折线图是兄弟。因此,当您从图表中 $broadcast 一个事件时,它没有 children,也没有人听到它。

同样,如果您从图表中 $emit 和事件,那么它将被发射到 parent 作用域 (MainCtrl),然后在层次结构中向上到达 $rootScope。它永远不会到达线图

当您使用 $scope.$parent.$broadcast 时,您是在告诉 MainCtrl 将事件广播到它的 children,它恰好是图表和折线图,所以它起作用了。

长话短说 - angular 在这里按预期工作。

与浏览器事件不同,angular 事件不会冒泡然后又上升。他们是一种方式。

您可以让 MainCtrl 监听该事件,然后 re-broadcast 它:

在 MainCtrl 中:

$scope.$on('HIGH_CHART....', function() {
    //rebroadcast to children
    var args = Array.prototype.shift.apply(arguments);
    $scope.$broadcast('HIGH_CHART.....', args )
};

(或类似的东西。您必须从参数中删除第一个元素,然后使用其余参数调用 broadcast - 在问题范围之外)。