千锋教育-做有情怀、有良心、有品质的IT职业教育机构

400-811-9990
当前位置:首页  >  技术文章  >  正文

重写事件抛发接收机制原理

时间:2022-07-28 16:59      来源:千锋教育 作者:qyf

  关于js中事件侦听和抛发机制的一些基础简单重构,通过这个简单重构了解中介者模式的工作方式,以下就是要做的简单重构方案。

重写事件抛发接收机制原理

  思路:

  创建EmitterTarget类和EmitterEvent类。

  EmitterTarget类主要使用了中介模式+观察者模式

  其中EmitterTarget类的实例化属性list充当中介角色,每当执行add方法时,给EmitterTarget类的实例化对象注册事件名称及触发函数;每当该对象执行remove方法时,从list列表中移除注册的事件及触发函数;

  dispatchEvent方法主要是发送事件对象本体,目的是为了在指定时刻触发事件函数以及传递数据参数。

  ==EmitterTarget类实例化对象本身就是观察者,观察者的特点是有add,remove,触发改变的函数(update或这里的dispatchEvent),以及应该有用于存放注册信息的属性或者单例对象。

  ==EmitterEvent类主要是用来创建事件对象本身,在创建时声明需要触发的事件类型以及需要携带的参数。

  EmitterTarget.ts代码如下:

  import EmitterEvent from "./EmitterEvent"; 

  interface IEvent{//中介者即存储实例化对象绑定的事件的list的数据规范接口

  [key:string]:Array;//key是事件名,value是触发事件函数数组

  }

  export default class EmitterTarget{

  private list:IEvent={};//私有变量list,只用于方法内部数据存储通信

  constructor(){

  }

  public addEventListener(type:string,handler:Function):void{

  if(!this.list[type])this.list[type]=[];//根据实例化对象传进来的事件类型判断list列表中是否注册该事件类型,如果没注册过,则创建这个字段

  var index=this.list[type].indexOf(handler);//看对应的事件中绑定的触发函数数组中是否存在这个触发函数

  if(index>-1) this.list[type][index]=handler;//存在则覆盖

  this.list[type].push(handler);//如果触发函数之前没有则在对应事件绑定的触发函数数组中新增

  }

  public removeEventListener(type:string,handler?:Function):void{

  if(!this.list[type])return;//如果list注册表中无事件注册,则删除无意义,直接返回

  if(handler===undefined){//如果调用该方法没有传要删除事件类型对应的触发函数就直接将该事件类型对应的全部触发函数删除

  for(var i=0;i<this.list[type].length;i++){< p="">

  this.list[type][i]=null;

  }

  this.list[type].length=0;

  return;

  }

  var index=this.list[type].indexOf(handler as Function);//这里用了断言,传进来了事件对应的触发函数,所以这里直接删除指定的那个

  if(index<0) return;

  this.list[type][index]=null;

  }

  public dispatchEvent(evt:EmitterEvent):void{//抛发事件

  if(!evt.type) throw new Error("错误的事件类型");//要抛发的事件一定要有事件类型

  evt.currentTarget=this;//抛发先给参数,将抛发事件的主人绑定给这个抛发事件对象,以便后面注册列表,事件类型对应的触发函数中需要使用到

  // var target=this;

  // while(target){//这里相当于循环深度递归,去冒泡一直找当前this的父元素...(用于dom元素)

  // if(target.parentElement)evt.path.push(target.parentElement);

  // target=target.parentElement;

  // }

  if(!this.list[evt.type]) return;//再次重复一次,必须声明事件类型

  for(var i:number=0;i<this.list[evt.type].length;i++){ p="" 根据事件类型去注册表里找对应的触发函数,这里执行的同时还要改变内部this执向<="">

  if(this.list[evt.type][i]) (this.list[evt.type][i] as Function).call(this,evt);

  }

  for (var j: number = 0; j < this.list[evt.type].length; j++){//这里再做了一次操作,在执行完注册表内事件类型对应的触发函数后,去将触发函数数组中为null的触发函数位置取消

  // (可能程序的其他地方已经将数组里的某些触发函数删除了(执行removeEventListener方法), 但是没把占的位置取消, 这里将该位置取消了)

  if(!this.list[evt.type][j]){

  this.list[evt.type].splice(j,1);

  j--;//splice()后j--是表示删除之后j需要回退一步,因为这里是遍历操作,

  // 如果不回退则被删除元素后面那个元素就不会再被检测直接跳过

  }

  }

  }

  }

  EmitterTarget.ts代码如下:

  import EmitterTarget from "./EmitterTarget";

  export default class EmitterEvent{

  public type:string;

  public currentTarget?:EmitterTarget;

  //target.dispatchEvent(evt);如这里的evt.currentTarget===target(在dispatchEvent方法内部绑定evt.currentTarget=this)

  public data?:object;//!!!注意这里的传的数据是用于注册的事件类型的触发函数中;

  constructor(type:string,data?:object){//创建抛发的事件,主要有是事件类型,携带的数据,

  this.type=type;

  this.data=data;

  }

  }

  使用demo:

  1.定义需要使用事件抛发的类

  import { IncomingMessage, ServerResponse } from "http";

  import EmitterEvent from "./EmitterEvent";

  import EmitterTarget from "./EmitterTarget";

  import IRes from "./IRes";

  import ResDataShow from "./ResDataShow";

  interface IResData{

  req:IncomingMessage;

  res:ServerResponse;

  data?:object;

  }

  export default class Main extends EmitterTarget{//main继承了EmitterTarget,所以这里有隐藏的list属性,用来充当注册表的角色

  private static _instance?:Main;

  constructor(){//给main的每个实例化对象都执行侦听ServerVo.DATA_LIST事件

  super();

  this.addEventListener(ServerVo.DATA_LIST,(e:EmitterEvent)=>this.dataHandler(e));//执行事件侦听方法时,在注册表中注册事件及其触发函数

  }

  static get instance():Main

  {

  if(!Main._instance) Main._instance=new Main();

  return Main._instance;

  }

  private dataHandler(e:EmitterEvent){//事件侦听的触发函数即回调函数

  var data:IResData=e.data as IResData;

  var command:IRes;

  command=new ResDataShow();

  command.exec(data.req,data.res,data.data);

  }

  }

  2.具体抛发操作

  import EmitterEvent from "./EmitterEvent";

  import Main from "./Main";

  var evt=new EmitterEvent(type,{req:req,res:res,data:dataObj});

  Main.instance.dispatchEvent(evt);//抛发事件,触发instance单例的绑定的函数

  更多关于“前端培训”的问题,欢迎咨询千锋教育在线名师。千锋教育多年办学,课程大纲紧跟企业需求,更科学更严谨,每年培养泛IT人才近2万人。不论你是零基础还是想提升,都可以找到适合的班型,千锋教育随时欢迎你来试听。

相关文章

  • 北京总部地址:北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
    北京沙河校区:北京市昌平区沙阳路18号北京科技职业技术学院广场服务楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 深圳校区地址:深圳市宝安区宝安大道5010号西部硅谷B座A区6层A605/B座C区1层108
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 上海校区地址:上海市宝山区同济支路199号智慧七立方3号楼2-4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 广州校区地址:广州市白云区永平街永泰学山塘学山文化创意谷A1栋六楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 郑州二七区校区地址:郑州市二七区航海中路60号海为科技园C区10层
    郑州高新区校区地址:郑州市高新区金梭路与银杏路交叉口教育科技产业园南门D座4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 大连校区地址:辽宁省大连市高新园区爱贤街10号大连设计城A座901
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 武汉金融港校区地址:武汉市东新区光谷大道77号金融港B18栋三楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 成都校区地址:成都市高新区肖家河沿街138号肖家河大厦三楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 西安校区地址:西安市雁塔区高新六路52号立人科技C座西区4楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 杭州旺田校区:浙江省杭州市江干区九堡旺田书画城A座4层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 青岛校区地址:青岛市市北区龙城路31号卓越世纪中心4号楼5层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 重庆校区地址:重庆市九龙坡区科园一路3号渝高大厦9楼
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 长沙校区地址:湖南省长沙市岳麓区麓谷企业广场A2栋三单元306号
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 哈尔滨校区地址:哈尔滨市松北区世泽路689号 科技创新城4号楼1101
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 南京校区地址:南京市建邺区应天大街780号弘辉产业园1栋2层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 太原校区地址:太原市小店区长治路230号能源互联网大厦6层
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 沈阳校区地址:辽宁省沈阳市浑南区世纪路16号东大软件园B园B1座A201
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 合肥校区地址:合肥市包河区徽州大道396号东方广场B座12A
    咨询电话:400-811-9990
    面授课程:HTML5大前端培训、JavaEE+分布式开发培训、Python全栈+人工智能培训、全链路UI/UE设计培训、云计算培训、全栈软件测试培训、大数据+人工智能培训、智能物联网+嵌入式培训、Unity游戏开发培训、Go语言开发培训、PHP全栈+服务器集群培训、网络安全培训、互联网营销培训、好程序员
    认证课程:软考、、PMP认证、红帽RHCE认证
  • 千锋教育服务号

    关注千锋学习站小程序
    随时随地免费学习课程

  • 千锋教育移动站

    扫一扫快速进入
    千锋移动端页面

  • 千锋互联服务号

    扫码匿名提建议
    直达CEO信箱