溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

js重構(gòu)怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2022-03-24 15:24:18 來源:億速云 閱讀:152 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“js重構(gòu)怎么實(shí)現(xiàn)”的相關(guān)知識(shí),小編通過實(shí)際案例向大家展示操作過程,操作方法簡單快捷,實(shí)用性強(qiáng),希望這篇“js重構(gòu)怎么實(shí)現(xiàn)”文章能幫助大家解決問題。

  思路:

  創(chuàng)建EmitterTarget類和EmitterEvent類。

  EmitterTarget類主要使用了中介模式+觀察者模式

  其中EmitterTarget類的實(shí)例化屬性list充當(dāng)中介角色,每當(dāng)執(zhí)行add方法時(shí),給EmitterTarget類的實(shí)例化對(duì)象注冊(cè)事件名稱及觸發(fā)函數(shù);每當(dāng)該對(duì)象執(zhí)行remove方法時(shí),從list列表中移除注冊(cè)的事件及觸發(fā)函數(shù);

  dispatchEvent方法主要是發(fā)送事件對(duì)象本體,目的是為了在指定時(shí)刻觸發(fā)事件函數(shù)以及傳遞數(shù)據(jù)參數(shù)。

  ==EmitterTarget類實(shí)例化對(duì)象本身就是觀察者,觀察者的特點(diǎn)是有add,remove,觸發(fā)改變的函數(shù)(update或這里的dispatchEvent),以及應(yīng)該有用于存放注冊(cè)信息的屬性或者單例對(duì)象。

  ==EmitterEvent類主要是用來創(chuàng)建事件對(duì)象本身,在創(chuàng)建時(shí)聲明需要觸發(fā)的事件類型以及需要攜帶的參數(shù)。

  EmitterTarget.ts代碼如下:

  import EmitterEvent from "./EmitterEvent";

  interface IEvent{//中介者即存儲(chǔ)實(shí)例化對(duì)象綁定的事件的list的數(shù)據(jù)規(guī)范接口

  [key:string]:Array<Function | null>;//key是事件名,value是觸發(fā)事件函數(shù)數(shù)組

  }

  export default class EmitterTarget{

  private list:IEvent={};//私有變量list,只用于方法內(nèi)部數(shù)據(jù)存儲(chǔ)通信

  constructor(){

  }

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

  if(!this.list[type])this.list[type]=[];//根據(jù)實(shí)例化對(duì)象傳進(jìn)來的事件類型判斷l(xiāng)ist列表中是否注冊(cè)該事件類型,如果沒注冊(cè)過,則創(chuàng)建這個(gè)字段

  var index=this.list[type].indexOf(handler);//看對(duì)應(yīng)的事件中綁定的觸發(fā)函數(shù)數(shù)組中是否存在這個(gè)觸發(fā)函數(shù)

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

  this.list[type].push(handler);//如果觸發(fā)函數(shù)之前沒有則在對(duì)應(yīng)事件綁定的觸發(fā)函數(shù)數(shù)組中新增

  }

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

  if(!this.list[type])return;//如果list注冊(cè)表中無事件注冊(cè),則刪除無意義,直接返回

  if(handler===undefined){//如果調(diào)用該方法沒有傳要?jiǎng)h除事件類型對(duì)應(yīng)的觸發(fā)函數(shù)就直接將該事件類型對(duì)應(yīng)的全部觸發(fā)函數(shù)刪除

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

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

  }

  this.list[type].length=0;

  return;

  }

  var index=this.list[type].indexOf(handler as Function);//這里用了斷言,傳進(jìn)來了事件對(duì)應(yīng)的觸發(fā)函數(shù),所以這里直接刪除指定的那個(gè)

  if(index<0) return;

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

  }

  public dispatchEvent(evt:EmitterEvent):void{//拋發(fā)事件

  if(!evt.type) throw new Error("錯(cuò)誤的事件類型");//要拋發(fā)的事件一定要有事件類型

  evt.currentTarget=this;//拋發(fā)先給參數(shù),將拋發(fā)事件的主人綁定給這個(gè)拋發(fā)事件對(duì)象,以便后面注冊(cè)列表,事件類型對(duì)應(yīng)的觸發(fā)函數(shù)中需要使用到

  // var target=this;

  // while(target){//這里相當(dāng)于循環(huán)深度遞歸,去冒泡一直找當(dāng)前this的父元素...(用于dom元素)

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

  //     target=target.parentElement;

  // }

  if(!this.list[evt.type]) return;//再次重復(fù)一次,必須聲明事件類型

  for(var i:number=0;i<this.list[evt.type].length;i++){//根據(jù)事件類型去注冊(cè)表里找對(duì)應(yīng)的觸發(fā)函數(shù),這里執(zhí)行的同時(shí)還要改變內(nèi)部this執(zhí)向

  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++){//這里再做了一次操作,在執(zhí)行完注冊(cè)表內(nèi)事件類型對(duì)應(yīng)的觸發(fā)函數(shù)后,去將觸發(fā)函數(shù)數(shù)組中為null的觸發(fā)函數(shù)位置取消

  // (可能程序的其他地方已經(jīng)將數(shù)組里的某些觸發(fā)函數(shù)刪除了(執(zhí)行removeEventListener方法), 但是沒把占的位置取消, 這里將該位置取消了)

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

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

  j--;//splice()后j--是表示刪除之后j需要回退一步,因?yàn)檫@里是遍歷操作,

  // 如果不回退則被刪除元素后面那個(gè)元素就不會(huì)再被檢測(cè)直接跳過

  }

  }

  }

  }

  EmitterTarget.ts代碼如下:

  import EmitterTarget from "./EmitterTarget";

  export default class EmitterEvent{

  public type:string;

  public currentTarget?:EmitterTarget;

  //target.dispatchEvent(evt);如這里的evt.currentTarget===target(在dispatchEvent方法內(nèi)部綁定evt.currentTarget=this)

  public data?:object;//!?。∽⒁膺@里的傳的數(shù)據(jù)是用于注冊(cè)的事件類型的觸發(fā)函數(shù)中;

  constructor(type:string,data?:object){//創(chuàng)建拋發(fā)的事件,主要有是事件類型,攜帶的數(shù)據(jù),

  this.type=type;

  this.data=data;

  }

  }

  使用demo:

  1.定義需要使用事件拋發(fā)的類

  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屬性,用來充當(dāng)注冊(cè)表的角色

  private static _instance?:Main;

  constructor(){//給main的每個(gè)實(shí)例化對(duì)象都執(zhí)行偵聽ServerVo.DATA_LIST事件

  super();

  this.addEventListener(ServerVo.DATA_LIST,(e:EmitterEvent)=>this.dataHandler(e));//執(zhí)行事件偵聽方法時(shí),在注冊(cè)表中注冊(cè)事件及其觸發(fā)函數(shù)

  }

  static get instance():Main

  {

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

  return Main._instance;

  }

  private dataHandler(e:EmitterEvent){//事件偵聽的觸發(fā)函數(shù)即回調(diào)函數(shù)

  var data:IResData=e.data as IResData;

  var command:IRes;

  command=new ResDataShow();

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

  }

  }

  2.具體拋發(fā)操作

  import EmitterEvent from "./EmitterEvent";

  import Main from "./Main";

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

  Main.instance.dispatchEvent(evt);//拋發(fā)事件,觸發(fā)instance單例的綁定的函數(shù)

關(guān)于“js重構(gòu)怎么實(shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI