AngularJS 事件发布机制


Posted in Javascript onAugust 28, 2018

问题描述

未读消息提醒

当器具用户或技术机构对非强检器具检校申请发布新的意见时,需要对对方进行消息通知。

后台很简单,本文主要解决前台遇到的问题。

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 事件发布机制

阅读时重新执行指令

下图就是该实现的难点。

该用户有一条未读消息,当用户点击阅读这条消息时,将该消息的状态设置为已读,然后右上角的未读条数同时修改。但是点击这个事件是发生在控制器中,而消息又是一个额外的指令,两者毫无联系。

AngularJS 事件发布机制

AngularJS的精髓就是Scope,这是两个Scope,页面内容是我们的控制器Scope,右上角的消息处是我们的未读消息指令Scope

如若是简单的父子Scope关系,我们可以从控制器传参数到指令,指令watch这个参数,根据控制器对参数的变动让指令做出响应。但是这两个Scope毫无关系,我们怎么办呢?

AngularJS 事件发布机制

事件发布

查阅了相关资料,AngularJSScope可以发布事件。

$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();
      }
    };
  });

AngularJS 事件发布机制

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
css把超出的部分显示为省略号的方法兼容火狐
Jul 23 Javascript
网页中CDATA标记的说明
Sep 12 Javascript
基于jquery的拖动布局插件
Nov 25 Javascript
jquery获取iframe中的dom对象(两种方法)
Jul 02 Javascript
js中函数声明与函数表达式
Jun 03 Javascript
jquery中object对象循环遍历的方法
Dec 18 Javascript
浅析jquery数组删除指定元素的方法:grep()
May 19 Javascript
详解angularJS动态生成的页面中ng-click无效解决办法
Jun 19 Javascript
微信小程序 sha1 实现密码加密实例详解
Jul 06 Javascript
Vue文件配置全局变量的实例
Sep 06 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
Feb 22 Javascript
Vue.js的模板语法详解
Feb 16 Javascript
vue.js 添加 fastclick的支持方法
Aug 28 #Javascript
深入理解JavaScript 中的匿名函数((function() {})();)与变量的作用域
Aug 28 #Javascript
对vue事件的延迟执行实例讲解
Aug 28 #Javascript
快速解决vue在ios端下点击响应延时的问题
Aug 27 #Javascript
微信小程序按钮去除边框线分享页面功能
Aug 27 #Javascript
Vue2 监听属性改变watch的实例代码
Aug 27 #Javascript
Vue 实现展开折叠效果的示例代码
Aug 27 #Javascript
You might like
PHP新手上路(九)
2006/10/09 PHP
php !function_exists(&quot;T7FC56270E7A70FA81A5935B72EACBE29&quot;))代码解密
2011/01/07 PHP
对于PHP 5.4 你必须要知道的
2013/08/07 PHP
Codeigniter上传图片出现“You did not select a file to upload”错误解决办法
2014/06/12 PHP
PHP使用内置dir类实现目录遍历删除
2015/03/31 PHP
Laravel的throttle中间件失效问题解决方法
2016/10/09 PHP
ThinkPHP 在阿里云上的nginx.config配置实例详解
2017/10/11 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
2020/02/23 PHP
JavaScript Event学习第八章 事件的顺序
2010/02/07 Javascript
Jquery焦点与失去焦点示例应用
2014/06/10 Javascript
JS动态创建DOM元素的方法
2015/06/09 Javascript
AngularJS中的过滤器使用详解
2015/06/16 Javascript
JS实现弹出浮动窗口(支持鼠标拖动和关闭)实例详解
2015/08/06 Javascript
JavaScript实现表格快速变色效果代码
2015/08/19 Javascript
node.js入门实例helloworld详解
2015/12/23 Javascript
JavaScript实现in-place思想的快速排序方法
2016/08/07 Javascript
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
Bootstrap在线电子商务网站实战项目5
2016/10/14 Javascript
AngulerJS学习之按需动态加载文件
2017/02/13 Javascript
详解Angular-Cli中引用第三方库
2017/05/21 Javascript
JS实现电脑虚拟键盘打字测试
2020/06/24 Javascript
Vue 防止短时间内连续点击后多次触发请求的操作
2020/11/11 Javascript
python sys,os,time模块的使用(包括时间格式的各种转换)
2018/04/27 Python
Python实现注册、登录小程序功能
2018/09/21 Python
python 协程中的迭代器,生成器原理及应用实例详解
2019/10/28 Python
python-numpy-指数分布实例详解
2019/12/07 Python
Python selenium页面加载慢超时的解决方案
2020/03/18 Python
python按顺序重命名文件并分类转移到各个文件夹中的实现代码
2020/07/21 Python
Python 保存加载mat格式文件的示例代码
2020/08/04 Python
关于python3.9安装wordcloud出错的问题及解决办法
2020/11/02 Python
Html5页面点击遮罩层背景关闭遮罩层
2020/11/30 HTML / CSS
英国蛋糕装饰用品一站式商店:Craft Company
2019/03/18 全球购物
初中体育教学反思
2014/01/14 职场文书
文秘人员工作职责
2014/01/31 职场文书
信息专业毕业生五年职业规划参考
2014/02/06 职场文书
2016党员入党决心书
2015/09/22 职场文书