AngularJS 事件发布机制
问题描述
未读消息提醒
当器具用户或技术机构对非强检器具检校申请发布新的意见时,需要对对方进行消息通知。
后台很简单,本文主要解决前台遇到的问题。
历史遗留
这是我的消息遗留下来的统计未读消息的指令,用到了缓存supercache
。
一眼看去应该能发现这个if...else
的问题,第一次请求,将数据放到缓存里,之后就一直从缓存中取了,这肯定有问题啊!原来有1
条消息,然后点击查看,然后这个指令仍然是从缓存中取的数据,还显示一条。
angular.module('webappapp') .directive('yunzhiunreadmessagecount', function(tomessageservice, supercache) { return { template: '', restrict: 'e', // 元素 link: function postlink(scope, element) { // 判断缓存中是否存在未读消息数量 if (typeof supercache.get('unreadmessagecount') === 'undefined') { // 获取当前用户的所有未读收件消息 tomessageservice.pagereceiveunreadmessageofcurrentuser(undefined, function(data) { // 存入缓存 supercache.put('unreadmessagecount', data.totalelements); // 显示文本信息 element.text(supercache.get('unreadmessagecount')); }); } else { // 显示文本信息 element.text(supercache.get('unreadmessagecount')); } } }; });
功能实现
注销时清除缓存
注销时如果不清除缓存,下一个用户登录时用的就是上一用户留下来的缓存,造成信息提示错误。
阅读时重新执行指令
下图就是该实现的难点。
该用户有一条未读消息,当用户点击阅读这条消息时,将该消息的状态设置为已读,然后右上角的未读条数同时修改。但是点击这个事件是发生在控制器中,而消息又是一个额外的指令,两者毫无联系。
angularjs
的精髓就是scope
,这是两个scope
,页面内容是我们的控制器scope
,右上角的消息处是我们的未读消息指令scope
。
如若是简单的父子scope
关系,我们可以从控制器传参数到指令,指令watch
这个参数,根据控制器对参数的变动让指令做出响应。但是这两个scope
毫无关系,我们怎么办呢?
事件发布
查阅了相关资料,angularjs
中scope
可以发布事件。
$broadcast(name, args);
dispatches an event name downwards to all child scopes (and their children) notifying the registered $rootscope.scope listeners.
向下分发一个事件给他的所有子scope
,通知已注册的scope
。
$emit(name, args);
dispatches an event name upwards through the scope hierarchy notifying the registered $rootscope.scope listeners.
与$broadcast
类似,只不过这个是用来向上发布事件的。
$on(name, listener);
listens on events of a given type.
监听一个给定类型的事件。
实例说明angularjs $broadcast $emit $on的用法
<div ng-controller="parentctrl"> //父级 <div ng-controller="selfctrl"> //自己 <a ng-click="click()">click me</a> <div ng-controller="childctrl"></div> //子级 </div> <div ng-controller="broctrl"></div> //平级 </div>
js代码
appcontrollers.controller('selfctrl', function($scope) { $scope.click = function () { $scope.$broadcast('to-child', 'child'); $scope.$emit('to-parent', 'parent'); } }); appcontrollers.controller('parentctrl', function($scope) { $scope.$on('to-parent', function(d,data) { console.log(data); //父级能得到值 }); $scope.$on('to-child', function(d,data) { console.log(data); //子级得不到值 }); }); appcontrollers.controller('childctrl', function($scope){ $scope.$on('to-child', function(d,data) { console.log(data); //子级能得到值 }); $scope.$on('to-parent', function(d,data) { console.log(data); //父级得不到值 }); }); appcontrollers.controller('broctrl', function($scope){ $scope.$on('to-parent', function(d,data) { console.log(data); //平级得不到值 }); $scope.$on('to-child', function(d,data) { console.log(data); //平级得不到值 }); });
点击click me的输出结果
child
parent
代码实现
$rootscope
考虑到这两个控制器与指令之间scope
的关系,无论是向上还是向下可能都接收不到。
这里直接用$rootscope
向下发布事件,保证所有scope
都能获取到该事件。免得去考虑当前scope
与目的scope
之间的关系。
// 广播发布reloadmessagecount事件,重新计算未读消息数量 $rootscope.$broadcast('reloadmessagecount');
因为考虑到各个层之间的职责关系,我认为:事件发布应该方法控制器中,而不应该放在service
中,service
就等着被别人调用,不应该与其他文件有耦合关系,否则改起来很难改。
$on
重构指令,使用$on
监听事件发布,执行相应的逻辑重新显示右上角的未读消息数。
angular.module('webappapp') .directive('yunzhiunreadmessagecount', function(tomessageservice, supercache) { return { template: '<b ng-if="count">{{ count }}</b>', restrict: 'e', // 元素 link: function postlink(scope) { var self = this; self.init = function() { self.computemessagecount(); }; // 计算未读消息数量 self.computemessagecount = function() { // 判断缓存中是否存在未读消息数量 if (angular.isundefined(supercache.get('unreadmessagecount'))) { // 获取当前用户的所有未读收件消息 tomessageservice.pagereceiveunreadmessageofcurrentuser(undefined, function(data) { // 存入缓存 supercache.put('unreadmessagecount', data.totalelements); // 显示 scope.count = supercache.get('unreadmessagecount'); }); } else { scope.count = supercache.get('unreadmessagecount'); } }; // 处理reloadmessagecount事件的处理逻辑 scope.$on('reloadmessagecount', function() { // 清除缓存 supercache.remove('unreadmessagecount'); // 计算未读消息数量 self.computemessagecount(); }); // 初始化 self.init(); } }; });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 南京特色美食小吃有哪些必须要打卡
下一篇: 广式腊肠怎么吃既美味又有营养