AngularJS 事件广播与接收 $broadcast,$emit,$on 作用域间通信 封装factory服务 发布订阅
不同作用域之间通过组合使用$broadcast,$emit,$on的事件广播机制来进行通信。
一、说明
1、广播
$broadcast
说明:将事件从父级作用域传播至本作用域及子级作用域。
格式:$broadcast(eventName,args)
$emit
说明:将事件从子级作用域传播至本作用域及父级作用域,直至根作用域。
格式:$emit(eventName,args)
2、接收
$on
说明:在作用域中监控从子级或父级作用域中传播过来的事件及相应的数据。
格式:$on(eventName,function(event,data){ })
event说明:
event.targetScope //获取传播事件的作用域
event.currentScope //获取接收事件的作用域
event.name //传播的事件的名称
event.stopPropagation() //阻止事件进行冒泡传播,仅在$emit事件中有效 ,当前作用域的上层作用域就不能再接收到消息事件
event.preventDefault() //阻止传播事件的发生
event.defaultPrevented //如果调用了preventDefault事件则返回true
二、例子
1、$scope.$emit
由子作用域向上级作用域传播数据。
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <meta charset="utf-8" /> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head> <script> var myApp = angular.module("myApp", []); //控制器Parent myApp.controller("Parent", function ($scope, $window) { $scope.name = "Parent"; $scope.$on("fromChild", function (event, data) { $window.alert("当前节点" + event.currentScope.name + ",截获到了来自" + data.divName + "的事件:" + event.name + ",它的作用是" + data.description); }); }); //控制器Child myApp.controller("Child", function ($scope, $window) { $scope.toTop = function () { //向上传播的事件,eventName:'fromChild', data:oneObject $scope.$emit("fromChild", { divName: "child", description: "向上播数据" }); }; }); </script> </head> <body> <form> <div ng-controller="Parent"> <div ng-controller="Child"> <input type="button" ng-click="toTop()" value="向上传播事件" /> </div> </div> </div> </form> </body> </html>
运行结果
2、event.stopPropagation()
阻止事件进行冒泡传播,仅在$emit事件中有效 ,当前作用域的上层作用域就不能再接收到消息事件。
上个例子原来应该rootScope也能收到事件消息,如果加一句event.stopPropagation(),rootScope就不能收到事件数据。
代码修改如下:
//控制器Parent myApp.controller("Parent", function ($scope, $window) { $scope.name = "Parent"; $scope.$on("fromChild", function (event, data) { $window.alert("当前节点" + event.currentScope.name + ",截获到了来自" + data.divName + "的事件:" + event.name + ",它的作用是" + data.description); event.stopPropagation(); }); });
三、项目实例
子作用域 childScope
<div class="panel-heading" style="border-radius: 5px 5px 0 0; background-color: #608FB7;padding:10px;"> <strong> {{focusedInput.inputType}}: #{{focusedInput.tooth.code2}} {{focusedInput.toothSurface|toToothSurfaceString}} {{focusedInput|toPerioInputPositionName}} </strong> </div> <div class="panel-body perio-input-board" style="padding:5px;margin-left:8px;"> <div style="width: 180px;float:left" class="perio-input-number-board"> <button type="button" class="btn btn-lg btn-default" ng-click="setValue(1)">1</button> </div> </div>
$emit向上层作用域发送消息广播,消息名称“perioInputFinished”,消息数据对象$scope.focusedInput
var setValue = function (value) { if ($scope.focusedInput) { $scope.$emit('perioInputFinished', $scope.focusedInput); } };
上级作用域parentScope
注册和接收,消息事件“perioInputFinished”,后又向子作用域广播,消息“perioValueChanged”,这样发送消息源作用域的兄弟作用域也可以收到消息事件
var init = function () {
//监控消息广播 $scope.$on('perioInputFinished', onPerioInputFinished); };
//监控到后,接收又广播
var onPerioInputFinished = function (event, perioInput) { $scope.$broadcast('perioValueChanged', perioInput); };
下级作用域childScope1
接收到“perioValueChanged”消息后,通过名称联系,进行最终处理,onPerioValueChanged
var onPerioValueChanged = function (event, perioInput) { if (perioInput.arch == $scope.arch && perioInput.toothSurface == $scope.toothSurface && (perioInput.inputType == 'PD' || perioInput.inputType == 'GM')) { refreshLine(); } }; var init = function () { $scope.$on('perioValueChanged', onPerioValueChanged); };
四、封装成服务factory方式
发布订阅模式
app.factory('eventAggregator', ['$log', '$rootScope', function ($log, $rootScope) { 'use strict'; var events = { ChargeOrderCreated: 'ChargeOrderCreated', SelectedEmployee: 'SelectedEmployee' }; var publish = function (event, eventData, sender) { $log.debug('[eventAggregator] publish(): ' + event); $rootScope.$broadcast(event, eventData, sender); }; $('body').on('sidebar-toggled', function (event, isCollapsed) { $rootScope.isSideBarCollapsed = isCollapsed; publish(events.AppSideBarToggled, null); }); return { events: events, publish: publish, subscribe: function (scope, event, callback) { return scope.$on(event, callback); } }; } ]);
使用方式:
订阅:$scope.$on
var subscribeEvent = function () {
eventAggregator.subscribe($scope, eventAggregator.events.ChargeOrderCreated, refresh);
};
发布:$rootScope.$broadcast
eventAggregator.publish(eventAggregator.events.ChargeOrderCreated, chargeData, eventSender);