您好,登錄后才能下訂單哦!
這篇文章主要介紹“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)。
免責(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)容。