使用$ scope。$ emit和$ scope。$ on

我怎么能发送我的$scope对象从一个控制器到另一个使用.$emit.$on方法?

 function firstCtrl($scope) { $scope.$emit('someEvent', [1,2,3]); } function secondCtrl($scope) { $scope.$on('someEvent', function(mass) { console.log(mass); }); } 

它不以我认为应该的方式工作。 如何$emit$on工作?

首先,亲子范围关系是重要的。 你有两种可能性来发出一些事件:

  • $broadcast – 向下调度事件给所有的子范围,
  • $emit – 通过作用域层次向上调度事件。

我不知道你的控制器(范围)关系,但有几个select:

  1. 如果secondCtrl范围是第二个secondCtrl范围的父级,那么你的代码应该在firstCtrl中用$broadcast代替$emit

     function firstCtrl($scope) { $scope.$broadcast('someEvent', [1,2,3]); } function secondCtrl($scope) { $scope.$on('someEvent', function(event, mass) { console.log(mass); }); } 
  2. 如果您的作用域之间没有父子关系,则可以将$rootScope注入控制器,并将该事件广播到所有子作用域(即secondCtrl )。

     function firstCtrl($rootScope) { $rootScope.$broadcast('someEvent', [1,2,3]); } 
  3. 最后,当你需要从子控制器分派事件到范围向上时,你可以使用$scope.$emit 。 如果firstCtrl范围是firstCtrl范围的父secondCtrl

     function firstCtrl($scope) { $scope.$on('someEvent', function(event, data) { console.log(data); }); } function secondCtrl($scope) { $scope.$emit('someEvent', [1,2,3]); } 

我还会build议第四个选项作为@zbynourbuild议的选项的更好select。

使用$rootScope.$emit而不是$rootScope.$broadcast而不pipe传输和接收控制器之间的关系。 这样,事件就保留在$rootScope.$$listeners的集合中,而使用$rootScope.$broadcast事件传播给所有的子作用域,其中大部分可能不会是该事件的监听者。 当然,在接收控制器的最后,您只需使用$rootScope.$on

对于这个选项,你必须记得销毁控制器的rootScope监听器:

 var unbindEventHandler = $rootScope.$on('myEvent', myHandler); $scope.$on('$destroy', function () { unbindEventHandler(); }); 

我怎样才能发送我的$范围对象从一个控制器到另一个使用。$ emit和。$方法?

你可以在应用层次结构中发送任何你想要的对象,包括$ scope

这里有一个关于如何广播发射工作的快速构思。

注意下面的节点; 全部嵌套在节点3中。使用广播并在发生这种情况时发出

注意:本例中每个节点的数量是任意的; 它可能很容易成为头号; 二号; 甚至数字1,348。 每个数字只是这个例子的一个标识符。 这个例子的要点是显示Angular控制器/指令的嵌套。

  3 ------------ | | ----- ------ 1 | 2 | --- --- --- --- | | | | | | | | 

看看这棵树。 你如何回答以下问题?

注意:还有其他方法可以回答这些问题,但在这里我们将讨论广播发射 。 此外,当读取下面的文本假设每个数字都有它自己的文件(指令,控制器)ex one.js,two.js,three.js。

节点1如何与节点3对话?

在文件one.js

 scope.$emit('messageOne', someValue(s)); 

在文件three.js中 – 所有需要通信的子节点的最高节点。

 scope.$on('messageOne', someValue(s)); 

节点2如何与节点3对话?

在文件two.js

 scope.$emit('messageTwo', someValue(s)); 

在文件three.js中 – 所有需要通信的子节点的最高节点。

 scope.$on('messageTwo', someValue(s)); 

节点3如何对节点1和/或节点2说话?

在文件three.js中 – 所有需要通信的子节点的最高节点。

 scope.$broadcast('messageThree', someValue(s)); 

在文件one.js && two.js无论你想要捕捉的文件或两者兼而有之。

 scope.$on('messageThree', someValue(s)); 

节点2如何与节点1对话?

在文件two.js

 scope.$emit('messageTwo', someValue(s)); 

在文件three.js中 – 所有需要通信的子节点的最高节点。

 scope.$on('messageTwo', function( event, data ){ scope.$broadcast( 'messageTwo', data ); }); 

在文件one.js

 scope.$on('messageTwo', someValue(s)); 

然而

当所有这些嵌套的子节点尝试像这样进行通信时,您将很快看到许多$ on$ broadcast$ emit

这是我喜欢做的事情。

在最上面的父节点(在这种情况下是3 ),这可能是你的父控制器…

所以,在文件three.js

 scope.$on('pushChangesToAllNodes', function( event, message ){ scope.$broadcast( message.name, message.data ); }); 

现在在任何子节点中,只需要$发出消息或使用$ on来捕获它。

注意:在不使用$ emit$ broadcast$ on的情况下,在一个嵌套path中串扰通常很容易,这意味着大多数情况下用于当您试图让节点1与节点2进行通信或反之亦然时。

节点2如何与节点1对话?

在文件two.js

 scope.$emit('pushChangesToAllNodes', sendNewChanges()); function sendNewChanges(){ // for some event. return { name: 'talkToOne', data: [1,2,3] }; } 

在文件three.js中 – 所有需要通信的子节点的最上面的节点。

我们已经处理了这个记得吗?

在文件one.js

 scope.$on('talkToOne', function( event, arrayOfNumbers ){ arrayOfNumbers.forEach(function(number){ console.log(number); }); }); 

您仍然需要使用每个特定的值来捕捉$ ,但是现在您可以在任何节点中创build任何您喜欢的内容,而无需担心在捕获和广播时如何通过父节点间隙获取消息通用pushChangesToAllNodes

希望这可以帮助…

为了将$ scope对象从一个控制器发送到另一个控制器,我将讨论$rootScope.$broadcast$rootScope.$emit ,因为它们被使用得最多。

案例1

$ rootScope $广播: –

 $rootScope.$broadcast('myEvent',$scope.data); $rootScope.$on('myEvent', function(event, data) {} 

$rootScope侦听器不会自动销毁。 你需要使用$destroy销毁它。 最好使用$scope.$on作为$scope监听器会被自动销毁,也就是$ scope被销毁。

 $scope.$on('myEvent', function(event, data) {} 

要么,

  var customeEventListener = $rootScope.$on('myEvent', function(event, data) { } $scope.$on('$destroy', function() { customeEventListener(); }); 

案例2:

。$ rootScope $发出:

  $rootScope.$emit('myEvent',$scope.data); $rootScope.$on('myEvent', function(event, data) {}//$scope.$on not works 

$ emit和$ broadcast的主要区别在于$ rootScope。$ emit事件必须使用$ rootScope。$ on来监听,因为发送的事件永远不会通过作用域树下来。
在这种情况下,你也必须像$ broadcast一样销毁监听器。

编辑:

我宁愿不使用$rootScope.$broadcast + $scope.$on但使用$rootScope.$emit+ $rootScope.$on 。 组合上的$rootScope.$broadcast + $scope.$on可能导致严重的性能问题。 那是因为这个事件会在所有的范围内都下降。

编辑2

在这个答案中解决的问题已经在angular.js 1.2.7版本中解决了。 $广播现在可以避免在未注册的作用域上冒泡,运行速度与$ emit类似。

您必须使用$ rootScope在同一应用程序中的控制器之间发送和捕获事件。 注入$ rootScope依赖关系到您的控制器。 这是一个工作的例子。

 app.controller('firstCtrl', function($scope, $rootScope) { function firstCtrl($scope) { { $rootScope.$emit('someEvent', [1,2,3]); } } app.controller('secondCtrl', function($scope, $rootScope) { function secondCtrl($scope) { $rootScope.$on('someEvent', function(event, data) { console.log(data); }); } } 

链接到$ scope对象的事件只能在所有者控制器中工作。 控制器之间的通信通过$ rootScope或Services完成。

您可以从您的控制器调用一个返回承诺的服务,然后在您的控制器中使用它。 并进一步使用$ emit或$ broadcast来通知其他控制器。 在我的情况下,我不得不通过我的服务进行http调用,所以我做了这样的事情:

 function ParentController($scope, testService) { testService.getList() .then(function(data){ $scope.list = testService.list; }) .finally(function(){ $scope.$emit('listFetched'); }) function ChildController($scope, testService){ $scope.$on('listFetched', function(event, data) { // use the data accordingly }) } 

我的服务看起来像这样

 app.service('testService',['$http', function($http){ this.list = []; this.getList = function () { return $http.get(someUrl) .then(function (response) { if (typeof response.data === 'object') { list = response.data.results; return response.data; } else { // invalid response return $q.reject(response.data); } }, function (response) { // something went wrong return $q.reject(response.data); }); } }]) 

这是我的function:

 $rootScope.$emit('setTitle', newVal.full_name); $rootScope.$on('setTitle', function(event, title) { if (scope.item) scope.item.name = title; else scope.item = {name: title}; }); 
 <!DOCTYPE html> <html> <head> <script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> <script> var app = angular.module('MyApp',[]); app.controller('parentCtrl',function($scope){ $scope.$on('MyEvent',function(event,data){ $scope.myData = data; }); }); app.controller('childCtrl',function($scope){ $scope.fireEvent = function(){ $scope.$emit('MyEvent','Any Data'); } }); </script> </head> <body ng-app="MyApp"> <div ng-controller="parentCtrl" ng-model="myName"> {{myData}} <div ng-controller="childCtrl"> <button ng-click="fireEvent()">Fire Event</button> </div> </div> </body> </html> 

下面的代码显示了事件分派到父控制器的两个子控制器(rootScope)

 <body ng-app="App"> <div ng-controller="parentCtrl"> <p>City : {{city}} </p> <p> Address : {{address}} </p> <div ng-controller="subCtrlOne"> <input type="text" ng-model="city"/> <button ng-click="getCity(city)">City !!!</button> </div> <div ng-controller="subCtrlTwo"> <input type="text" ng-model="address"/> <button ng-click="getAddrress(address)">Address !!!</button> </div> </div> </body> 
  var App = angular.module('App',[]); //parent controller App.controller('parentCtrl',parentCtrl); parentCtrl.$inject = ["$scope"]; function parentCtrl($scope) { $scope.$on('cityBoom',function(events,data){ $scope.city = data; }); $scope.$on('addrBoom',function(events,data){ $scope.address = data; }); } //sub controller one App.controller('subCtrlOne',subCtrlOne); subCtrlOne.$inject =['$scope']; function subCtrlOne($scope) { $scope.getCity=function(city){ $scope.$emit('cityBoom',city); } } //sub controller two App.controller('subCtrlTwo',subCtrlTwo); subCtrlTwo.$inject = ["$scope"]; function subCtrlTwo($scope) { $scope.getAddrress = function(addr) { $scope.$emit('addrBoom',addr); } } 

http://jsfiddle.net/shushanthp/zp6v0rut/

我最终添加了一个外部EventEmitter库作为服务项目,并在需要时注入。 所以我可以在任何地方“放射”和“打开”任何东西,而不必关心范围inheritance。 这样做麻烦较less,性能肯定更好。 也更可读性。

通配符支持: EventEmitter2

良好的performance: eventemitter3

其他select: 滴灌

可以使用范围来传播事件,将事件分派给子范围或子范围。

$ emit – 将事件传播给父项。 $ broadcast – 将事件传播给子节点。 $ on – 方法来监听由$ emit和$ broadcast传播的事件。

例如index.html

 <div ng-app="appExample" ng-controller="EventCtrl"> Root(Parent) scope count: {{count}} <div> <button ng-click="$emit('MyEvent')">$emit('MyEvent')</button> <button ng-click="$broadcast('MyEvent')">$broadcast('MyEvent')</button><br> Childrent scope count: {{count}} </div> </div> 

示例app.js

 angular.module('appExample', []) .controller('EventCtrl', ['$scope', function($scope) { $scope.count = 0; $scope.$on('MyEvent', function() { $scope.count++; }); }]); 

在这里你可以testing代码: http : //jsfiddle.net/zp6v0rut/41/

根据angularjs事件文档,接收端应该包含类似结构的参数

@params

– {Object}事件是包含事件信息的事件对象

– 被调用者传递的{Object}参数(注意,这只能是一个总是发送字典对象的更好的方法)

$scope.$on('fooEvent', function (event, args) { console.log(args) }); 从你的代码

另外,如果你试图获得一个共享的信息在不同的控制器上是可用的,还有另一种方法来实现这一点,这是angular度的服务。由于服务是单身信息可以存储和提取跨控制器。简单地创buildgetter setter函数在这个服务中,公开这些函数,在服务中创build全局variables并使用它们来存储信息

最简单的方法:

HTML

  <div ng-app="myApp" ng-controller="myCtrl"> <button ng-click="sendData();"> Send Data </button> </div> 

JavaScript的

  <script> var app = angular.module('myApp', []); app.controller('myCtrl', function($scope, $rootScope) { function sendData($scope) { var arrayData = ['sam','rumona','cubby']; $rootScope.$emit('someEvent', arrayData); } }); app.controller('yourCtrl', function($scope, $rootScope) { $rootScope.$on('someEvent', function(event, data) { console.log(data); }); }); </script>