我有一个footerController和codeScannerController,它有不同的视图。
angular.module('myApp').controller('footerController', ["$scope", function($scope) {}]);
angular.module('myApp').controller('codeScannerController', ["$scope", function($scope) {
console.log("start");
$scope.startScanner = function(){...
当我点击footer.html中的<li>
时,我应该在codeScannerController中获取此事件。
<li class="button" ng-click="startScanner()">3</li>
我认为可以通过$on
和$broadcast
来实现,但我不知道如何在任何地方找到示例。
答案 0 :(得分:614)
如果您想$broadcast
使用$rootScope
:
$scope.startScanner = function() {
$rootScope.$broadcast('scanner-started');
}
然后接收,使用控制器的$scope
:
$scope.$on('scanner-started', function(event, args) {
// do what you want to do
});
如果您愿意,可以在$broadcast
:
$rootScope.$broadcast('scanner-started', { any: {} });
然后收到它们:
$scope.$on('scanner-started', function(event, args) {
var anyThing = args.any;
// do what you want to do
});
Scope docs内的文档。
答案 1 :(得分:94)
首先,简要介绍$on()
, $broadcast()
and $emit()
:
.$on(name, listener)
- 按给定的name
.$broadcast(name, args)
- 通过所有孩子的$scope
广播一个事件.$emit(name, args)
- 向所有家长发送$scope
层级的活动,包括$rootScope
基于以下HTML(请参阅full example here):
<div ng-controller="Controller1">
<button ng-click="broadcast()">Broadcast 1</button>
<button ng-click="emit()">Emit 1</button>
</div>
<div ng-controller="Controller2">
<button ng-click="broadcast()">Broadcast 2</button>
<button ng-click="emit()">Emit 2</button>
<div ng-controller="Controller3">
<button ng-click="broadcast()">Broadcast 3</button>
<button ng-click="emit()">Emit 3</button>
<br>
<button ng-click="broadcastRoot()">Broadcast Root</button>
<button ng-click="emitRoot()">Emit Root</button>
</div>
</div>
触发事件将遍历$scopes
,如下所示:
$scope
$scope
然后$rootScope
$scope
然后控制器3 $scope
$scope
然后$rootScope
$scope
$scope
,控制器2 $scope
然后$rootScope
$rootScope
和$scope
将会看到(1,2,然后是3)$rootScope
用于触发事件的JavaScript(同样,您可以看到working example here):
app.controller('Controller1', ['$scope', '$rootScope', function($scope, $rootScope){
$scope.broadcastAndEmit = function(){
// This will be seen by Controller 1 $scope and all children $scopes
$scope.$broadcast('eventX', {data: '$scope.broadcast'});
// Because this event is fired as an emit (goes up) on the $rootScope,
// only the $rootScope will see it
$rootScope.$emit('eventX', {data: '$rootScope.emit'});
};
$scope.emit = function(){
// Controller 1 $scope, and all parent $scopes (including $rootScope)
// will see this event
$scope.$emit('eventX', {data: '$scope.emit'});
};
$scope.$on('eventX', function(ev, args){
console.log('eventX found on Controller1 $scope');
});
$rootScope.$on('eventX', function(ev, args){
console.log('eventX found on $rootScope');
});
}]);
答案 2 :(得分:26)
你应该知道的一件事是$ prefix指的是Angular方法,$$前缀指的是你应该避免使用的angular方法。
下面是一个示例模板及其控制器,我们将探讨$ broadcast / $ on如何帮助我们实现我们想要的目标。
<div ng-controller="FirstCtrl">
<input ng-model="name"/>
<button ng-click="register()">Register </button>
</div>
<div ng-controller="SecondCtrl">
Registered Name: <input ng-model="name"/>
</div>
控制器
app.controller('FirstCtrl', function($scope){
$scope.register = function(){
}
});
app.controller('SecondCtrl', function($scope){
});
我的问题是,当用户点击注册时,如何将名称传递给第二个控制器?您可能会提出多种解决方案,但我们将要使用的是使用$ broadcast和$ on。
$ broadcast vs $ emit
我们应该使用哪个? $ broadcast将向下传递给所有孩子的dom元素,$ emit将向所有祖先dom元素传递相反的方向。
避免在$ emit或$ broadcast之间做出决定的最佳方法是从$ rootScope进行通道并使用$ broadcast到其所有子节点。由于我们的dom元素是兄弟姐妹,这使我们的案例变得更容易。
添加$ rootScope并允许$ broadcast
app.controller('FirstCtrl', function($rootScope, $scope){
$scope.register = function(){
$rootScope.$broadcast('BOOM!', $scope.name)
}
});
注意我们添加了$ rootScope,现在我们使用$ broadcast(broadcastName,arguments)。对于broadcastName,我们想给它一个唯一的名称,以便我们可以在secondCtrl中捕获该名称。我选择了BOOM!纯娱乐。第二个论点&#39;论证&#39;允许我们将值传递给侦听器。
接收我们的广播
在我们的第二个控制器中,我们需要设置代码来收听我们的广播
app.controller('SecondCtrl', function($scope){
$scope.$on('BOOM!', function(events, args){
console.log(args);
$scope.name = args; //now we've registered!
})
});
真的那么简单。 Live Example
获得类似结果的其他方法
尽量避免使用这套方法,因为它既不高效也不易维护,但它是解决您可能遇到的问题的简单方法。
您通常可以通过使用服务或简化控制器来执行相同的操作。我们不会详细讨论这个问题,但我认为我只是提到完整性。
最后,请记住一个真正有用的广播,听取的是#destroy; $ destroy&#39;再次,您可以看到$表示它是供应商代码创建的方法或对象。无论如何,当控制器被破坏时,广播会播放$ destroy,你可能想听听它,知道你的控制器什么时候被删除。
答案 3 :(得分:1)
//Your broadcast in service
(function () {
angular.module('appModule').factory('AppService', function ($rootScope, $timeout) {
function refreshData() {
$timeout(function() {
$rootScope.$broadcast('refreshData');
}, 0, true);
}
return {
RefreshData: refreshData
};
}); }());
//Controller Implementation
(function () {
angular.module('appModule').controller('AppController', function ($rootScope, $scope, $timeout, AppService) {
//Removes Listeners before adding them
//This line will solve the problem for multiple broadcast call
$scope.$$listeners['refreshData'] = [];
$scope.$on('refreshData', function() {
$scope.showData();
});
$scope.onSaveDataComplete = function() {
AppService.RefreshData();
};
}); }());