如何使用$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
如何运作?
答案 0 :(得分:1483)
首先,父子范围关系很重要。你有两种可能发出一些事件:
$broadcast
- 将事件向下调度到所有子范围$emit
- 通过范围层次结构向上调度事件。我对你的控制器(范围)关系一无所知,但有几种选择:
如果firstCtrl
的范围是secondCtrl
范围的父级,则代码应该是。{
通过$emit
中的$broadcast
替换firstCtrl
:
function firstCtrl($scope)
{
$scope.$broadcast('someEvent', [1,2,3]);
}
function secondCtrl($scope)
{
$scope.$on('someEvent', function(event, mass) { console.log(mass); });
}
如果您的示波器之间没有父子关系
可以将$rootScope
注入控制器并广播该事件
所有子范围(即secondCtrl
)。
function firstCtrl($rootScope)
{
$rootScope.$broadcast('someEvent', [1,2,3]);
}
最后,当您需要从子控制器调度事件时
要向上调整范围,您可以使用$scope.$emit
。如果firstCtrl
的范围是secondCtrl
范围的父级:
function firstCtrl($scope)
{
$scope.$on('someEvent', function(event, data) { console.log(data); });
}
function secondCtrl($scope)
{
$scope.$emit('someEvent', [1,2,3]);
}
答案 1 :(得分:145)
我还建议第四个选项作为@zbynour提议选项的更好替代方案。
使用$rootScope.$emit
而不是$rootScope.$broadcast
,无论传输和接收控制器之间的关系如何。这样,事件保持在$rootScope.$$listeners
的集合内,而$rootScope.$broadcast
事件将传播到所有子范围,其中大多数可能不是该事件的监听者。当然,在接收控制器的最后,您只需使用$rootScope.$on
。
对于此选项,您必须记住销毁控制器的rootScope侦听器:
var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
unbindEventHandler();
});
答案 2 :(得分:109)
如何使用。$ emit和。$ on方法将$ scope对象从一个控制器发送到另一个控制器?
您可以在应用层次结构中发送所需的任何对象,包括 $ scope 。
以下是关于广播和发布工作原理的快速提示。
注意下面的节点;全部嵌套在节点3中。当您有这种情况时,您可以使用广播和发布。
注意:此示例中每个节点的数量是任意的;它很容易成为头号人物;二号;甚至是1,348号。每个数字只是此示例的标识符。这个例子的目的是显示Angular控制器/指令的嵌套。
3
------------
| |
----- ------
1 | 2 |
--- --- --- ---
| | | | | | | |
查看此树。您如何回答以下问题?
注意:还有其他方法可以回答这些问题,但在这里我们将讨论广播和发布。此外,当阅读下面的文本时,假设每个数字都有自己的文件(指令,控制器)e.x. 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's , $ broadcast's 和 $ emit's 强>
这是我喜欢做的事。
在最上面的PARENT NODE(在这种情况下 3 ...),这可能是你的父控制器......
所以,在文件 three.js
中scope.$on('pushChangesToAllNodes', function( event, message ){
scope.$broadcast( message.name, message.data );
});
现在,在任何子节点中,您只需 $ emit 消息或使用 $ on 捕获消息。
注意:通常很容易在一个嵌套路径中进行串扰而不使用 $ emit , $ broadcast 或 $ on ,这意味着大多数用例适用于您尝试让节点 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);
});
});
您仍然需要对要捕获的每个特定值使用 $ on ,但现在您可以在任何节点中创建任何您喜欢的内容,而无需担心如何获取消息当我们捕获并广播通用 pushChangesToAllNodes 时,跨父节点间隙。
希望这会有所帮助......
答案 3 :(得分:38)
要将$scope object
从一个控制器发送到另一个控制器,我会在这里讨论$rootScope.$broadcast
和$rootScope.$emit
,因为它们最常用。
案例1 :
$ $ rootScope广播: -
$rootScope.$broadcast('myEvent',$scope.data);//Here `myEvent` is event name
$rootScope.$on('myEvent', function(event, data) {} //listener on `myEvent` event
$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。必须使用$ rootScope。$ on来监听$ emit事件,因为发出的事件永远不会通过范围树传递。。
在这种情况下,你也必须像$ broadcast一样销毁监听器。
修改强>
我不想使用
$rootScope.$broadcast + $scope.$on
但是请使用$rootScope.$emit+ $rootScope.$on
。$rootScope.$broadcast + $scope.$on
组合可能会导致严重的性能问题。那是 因为事件将在所有范围内向下消失。
编辑2 :
此答案中解决的问题已在angular.js中得到解决 版本1.2.7。 $ broadcast现在避免冒泡未注册的范围 并且运行速度与$ emit一样快。
答案 4 :(得分:10)
您必须使用$ 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完成的。
答案 5 :(得分:6)
您可以从控制器中调用返回承诺的服务,然后在控制器中使用它。并进一步使用$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);
});
}
}])
答案 6 :(得分:4)
这是我的功能:
$rootScope.$emit('setTitle', newVal.full_name);
$rootScope.$on('setTitle', function(event, title) {
if (scope.item)
scope.item.name = title;
else
scope.item = {name: title};
});
答案 7 :(得分:4)
<!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>
答案 8 :(得分:3)
我最终添加了一个外部EventEmitter库作为服务项目,并将其注入我需要的任何地方。所以我可以在任何地方“发射”和“开启”任何地方,而无需关心范围继承。这种方式不那么麻烦,肯定会有更好的性能。对我来说也更具可读性。
通配符支持:EventEmitter2
表现良好:eventemitter3
其他选择:Drip
答案 9 :(得分:2)
下面的代码显示了将事件向上调度到父控制器的两个子控制器(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);
}
}
答案 10 :(得分:2)
Scope(s)可用于传播,将事件分派给范围子项或父项。
$ 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++;
});
}]);
在这里你可以测试代码: http://jsfiddle.net/zp6v0rut/41/
答案 11 :(得分:0)
根据angularjs事件文档,接收端应该包含具有类似
结构的参数@params
- {Object}事件是包含事件信息的事件对象
- 被调用者传递的{Object} args(注意,这只能是一个总是在字典对象中发送的更好)
$scope.$on('fooEvent', function (event, args) { console.log(args) });
从你的代码
另外,如果你试图让不同控制器可以获得共享的信息,那么还有另一种方法可以实现这一点,那就是角度服务。由于服务是单例,因此可以跨控制器存储和获取信息。在该服务中创建getter和setter函数,公开这些函数,在服务中创建全局变量并使用它们来存储信息
答案 12 :(得分:0)
最简单的方法:
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>