practice/alternative 在 angularjs 中使用 $broadcast/$on 触发事件的最佳方式是什么?

What is best practice/alternative to use $broadcast/$on in triggering events in angularjs?

我有一个场景,我想在不同应用程序中的同级控制器之间进行通信。所以我创建了示例 demo,它使用发布者-订阅者服务来广播和监听事件。但是订阅事件的代码在控制器中。所以我想了解这是否是最佳做法?实现相同的替代方法是什么,举个例子?

我指出了以下情况 –
controllerA 广播事件,controllerB 和 controllerC 监听它 (1-Many)

var app = angular.module('app', []);

app.controller('controllerA', ['$scope', 'pubsubService', controllerA]);

function controllerA($scope, pubsubService) {
  $scope.teamName = '';
  $scope.changeTeam = function() {
    pubsubService.Publish("changeNameEvent", {
      filterTeam: $scope.teamName
    });
  };
}

app.controller('controllerB', ['$scope', 'pubsubService', controllerB]);

function controllerB($scope, pubsubService) {
  var callbackNameChanged = function(message) {
    $scope.team = message.filterTeam

  };
  pubsubService.Subscribe("changeNameEvent", $scope, callbackNameChanged);
}

app.controller('controllerC', ['$scope', 'pubsubService', controllerC]);

function controllerC($scope, pubsubService) {
  var callbackNameChanged = function(message) {
    $scope.team = message.filterTeam
  };
  pubsubService.Subscribe("changeNameEvent", $scope, callbackNameChanged);
}

app.factory("pubsubService", ["$rootScope", function($rootScope) {
  var Publish = function(message, item) {
    try {
      $rootScope.$broadcast(message, {
        item: item
      })
    } catch (e) {
      console.log(e.message)
    }
  };
  var Subscribe = function(message, $scope, handler) {
    try {
      $scope.$on(message, function(event, args) {
        handler(args.item)
      })
    } catch (e) {
      console.log(e.message)
    }
  };
  return {
    Publish: Publish,
    Subscribe: Subscribe
  }
}]);

Html代码:

<body class='container'>
  <div ng-controller="controllerA">
    <input data-ng-model="teamName" type="text" data-ng-change="changeTeam()" />    
  </div>
  <div ng-controller="controllerB">controllerB - You typed: {{team}}
    <br />
  </div>
  <div ng-controller="controllerC">controllerC - You typed:{{team}}</div>
</body>

分析后,我想出以下 solution 将订阅逻辑移动到带有“&”运算符参数的指令,该指令允许在父作用域上调用或评估 expression/function 并保留控制器代码到最小。因为在 99% 的情况下,将东西倾倒到控制器上是一个坏主意。除非它是范围变量或手表,否则您很可能会将其抽象为其他内容。

通过这种方式实现,我们可以使代码可重用、可测试和模块化。

app.directive('onChangeName', ['pubsubService', function(pubsubService) {
  return {
    restrict: 'EA',
    scope: {
      onNameChangeCallback: '&'
    },
    link: function(scope, element) {
      pubsubService.Subscribe("changeNameEvent", scope, function(message) {
        scope.onNameChangeCallback({
          message: message.filterTeam
        });
      });
    }
  };
}]);

app.controller('controllerB', function($scope){
  $scope.callbackNameChanged = function(message) {
    $scope.team = message
  };
});

app.controller('controllerC', function($scope){
  $scope.callbackNameChanged = function(message) {
     $scope.team = message
  };
});

Html代码

<div ng-controller="controllerB">
    <on-change-name on-name-change-callback="callbackNameChanged(message)"></on-change-name>
    controllerB - You typed: {{team}}
    <br />
</div>
<div ng-controller="controllerC">
    <on-change-name on-name-change-callback="callbackNameChanged(message)"></on-change-name>
    controllerC - You typed:{{team}}
</div>