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 相关文章推荐
JavaScript国旗变换效果代码
Aug 13 Javascript
javascript Demo模态窗口
Dec 06 Javascript
jquery弹出层类代码分享
Dec 27 Javascript
JavaScript实现更改网页背景与字体颜色的方法
Feb 02 Javascript
JS实现的表格操作类详解(添加,删除,排序,上移,下移)
Dec 22 Javascript
JQuery ztree带筛选、异步加载实例讲解
Feb 25 Javascript
原生js jquery ajax请求以及jsonp的调用方法
Aug 04 jQuery
inner join 内联与left join 左联的实例代码
Sep 18 Javascript
微信小程序实现商品属性联动选择
Feb 15 Javascript
微信小程序 textarea 层级过高问题简单解决方案
Oct 14 Javascript
基于JS实现table导出Excel并保留样式
May 19 Javascript
微信小程序实现可长按移动控件
Nov 01 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创建、获取cookie及基础要点分析
2015/01/26 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
PHP接收json 并将接收数据插入数据库的实现代码
2015/12/01 PHP
图片自动缩小 点击放大
2008/07/07 Javascript
检测是否已安装 .NET Framework 3.5的js脚本
2009/02/14 Javascript
浅析jQuery的链式调用之each函数
2010/12/03 Javascript
jquery 图片上传按比例预览插件集合
2011/05/28 Javascript
from 表单提交返回值用post或者是get方法实现
2013/08/21 Javascript
js中reverse函数的用法详解
2013/12/26 Javascript
jQuery中removeClass()方法用法实例
2015/01/05 Javascript
JavaScript中字符串分割函数split用法实例
2015/04/07 Javascript
基于jQuery实现的旋转彩圈实例
2015/06/26 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
vue项目创建并引入饿了么elementUI组件的步骤
2019/04/11 Javascript
Vue scrollBehavior 滚动行为实现后退页面显示在上次浏览的位置
2019/05/27 Javascript
微信小程序npm引入vant-weapp的踩坑记录
2019/08/01 Javascript
JsonProperty 的使用方法详解
2019/10/11 Javascript
JavaScript实现简单验证码
2020/08/24 Javascript
[01:45]典藏宝瓶2+祈求者身心——这就是DOTA2TI9总奖金突破3000万美元的秘密
2019/07/21 DOTA
Python数据可视化编程通过Matplotlib创建散点图代码示例
2017/12/09 Python
Python安装pycurl失败的解决方法
2018/10/15 Python
Python爬虫 批量爬取下载抖音视频代码实例
2019/08/16 Python
Python图像处理模块ndimage用法实例分析
2019/09/05 Python
python 爬虫百度地图的信息界面的实现方法
2019/10/27 Python
python实现高斯(Gauss)迭代法的例子
2019/11/20 Python
python生成特定分布数的实例
2019/12/05 Python
python连接mongodb集群方法详解
2020/02/13 Python
pycharm使用技巧之自动调整代码格式总结
2020/11/04 Python
优瑞自动咖啡机官网:Jura
2018/09/29 全球购物
物业电工岗位职责
2013/11/20 职场文书
中青班党性分析材料
2014/02/16 职场文书
2016年庆“七一”主题党日活动总结
2016/04/05 职场文书
《工作是最好的修行》读后感3篇
2019/12/13 职场文书
Python基于Tkinter开发一个爬取B站直播弹幕的工具
2021/05/06 Python
Mysql Innodb存储引擎之索引与算法
2022/02/15 MySQL
「魔法少女伊莉雅」美游粘土人开订
2022/03/21 日漫