本文翻译自:Working with $scope.$emit and $scope.$on
How can I send my $scope
object from one controller to another using .$emit
and .$on
methods? 如何使用.$emit
和.$on
方法将$scope
对象从一个控制器发送到另一个控制器?
function firstCtrl($scope) {
$scope.$emit('someEvent', [1,2,3]);
}
function secondCtrl($scope) {
$scope.$on('someEvent', function(mass) { console.log(mass); });
}
It doesn't work the way I think it should. 它不像我认为的那样工作。 How do $emit
and $on
work? $emit
和$on
work如何运作?
#1楼
参考:https://stackoom.com/question/yqdK/使用-scope-emit和-scope-on
#2楼
First of all, parent-child scope relation does matter. 首先,父子范围关系确实很重要。 You have two possibilities to emit some event: 你有两种可能发出一些事件:
-
$broadcast
-- dispatches the event downwards to all child scopes,$broadcast
- 将事件向下发送到所有子范围, -
$emit
-- dispatches the event upwards through the scope hierarchy.$emit
- 通过范围层次结构向上调度事件。
I don't know anything about your controllers (scopes) relation, but there are several options: 我对控制器(范围)关系一无所知,但有几种选择:
If scope of
firstCtrl
is parent of thesecondCtrl
scope, your code should work by replacing$emit
by$broadcast
infirstCtrl
: 如果范围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); }); }
In case there is no parent-child relation between your scopes you can inject
$rootScope
into the controller and broadcast the event to all child scopes (ie alsosecondCtrl
). 如果您的范围之间没有父子关系,您可以将$rootScope
注入控制器并将事件广播到所有子范围(即secondCtrl
)。function firstCtrl($rootScope) { $rootScope.$broadcast('someEvent', [1,2,3]); }
Finally, when you need to dispatch the event from child controller to scopes upwards you can use
$scope.$emit
. 最后,当您需要将子控制器中的事件调度到范围向上时,您可以使用$scope.$emit
。 If scope offirstCtrl
is parent of thesecondCtrl
scope: 如果firstCtrl
范围是firstCtrl
范围的父secondCtrl
:function firstCtrl($scope) { $scope.$on('someEvent', function(event, data) { console.log(data); }); } function secondCtrl($scope) { $scope.$emit('someEvent', [1,2,3]); }
#3楼
You can call a service from your controller that returns a promise and then use it in your controller. 您可以从控制器调用返回承诺的服务,然后在控制器中使用它。 And further use $emit
or $broadcast
to inform other controllers about it. 并进一步使用$emit
或$broadcast
来通知其他控制器。 In my case, I had to make http calls through my service, so I did something like this : 在我的情况下,我不得不通过我的服务进行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
})
}
and my service looks like this 我的服务看起来像这样
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);
});
}
}])
#4楼
I would additionally suggest a 4th option as a better alternative to the proposed options by @zbynour. 我还建议第四个选项作为@zbynour提议选项的更好替代方案。
Use $rootScope.$emit
rather than $rootScope.$broadcast
regardless of the relationship between trasmitting and receiving controller. 无论传输和接收控制器之间的关系如何,都使用$rootScope.$emit
而不是$rootScope.$broadcast
。 That way, the event remains within the set of $rootScope.$$listeners
whereas with $rootScope.$broadcast
the event propagates to all children scopes, most of which will probably not be listeners of that event anyway. 这样,事件保持在$rootScope.$$listeners
的集合中,而使用$rootScope.$broadcast
,事件传播到所有子范围,其中大多数可能不是该事件的监听器。 And of course in the receiving controller's end you just use $rootScope.$on
. 当然,在接收控制器的最后,你只需使用$rootScope.$on
。
For this option you must remember to destroy the controller's rootScope listeners: 对于此选项,您必须记住销毁控制器的rootScope侦听器:
var unbindEventHandler = $rootScope.$on('myEvent', myHandler);
$scope.$on('$destroy', function () {
unbindEventHandler();
});
#5楼
This is my 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};
});
#6楼
<!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>