TP6 事件event與監(jiān)聽類listener

說(shuō)明:TP6的官方文檔很啰嗦,而且給出了若干并不良好的實(shí)踐方式。

先上答案:

1. 假設(shè)有自定義的事件如aaa,在event.php文件中l(wèi)isten數(shù)組里,添加一項(xiàng):鍵名為'aaa',鍵值為一個(gè)一維數(shù)組,里面是若干類名稱如BB::class,CC:;class,DD::class。

2. BB,CC,DD 都有一個(gè)handle方法,在需要執(zhí)行BB,CC,DD中handle方法的地方,寫上Event::trigger('aaa')

----------------------------------------------------------------------------------------------------

再說(shuō)原因:

事件的概念,可以理解為數(shù)組的一個(gè)key,該key對(duì)應(yīng)多個(gè)函數(shù)。類似于['eventName' => ['fun1','fun2']]

監(jiān)聽就是一直“監(jiān)視”某個(gè)事件是否完成(程序是否執(zhí)行到標(biāo)記位置),完成則執(zhí)行若干函數(shù),如上面的fun1和fun2。

觸發(fā),就是使事件變?yōu)橥瓿?執(zhí)行事件上所綁定的函數(shù)(監(jiān)聽器)。

即一個(gè)完整的事件監(jiān)聽流程分為: 定義事件,綁定監(jiān)聽器,觸發(fā)事件三個(gè)部分。

一個(gè)典型的事件,就是瀏覽器的文檔加載完畢。當(dāng)文檔加載完畢后,彈出廣告,歡迎語(yǔ)之類的。

這里的事件是 document.ready,監(jiān)聽器是彈廣告歡迎,觸發(fā)動(dòng)作是瀏覽器完成的,加載完文檔就觸發(fā)。


舉一個(gè)常見的例子:填寫表單,提交表單,注冊(cè)完畢都是標(biāo)記(事件,鉤子), 注冊(cè)完畢后,給新帳號(hào)增加金幣,積分,登錄次數(shù)。


這里的事件,就是注冊(cè)完畢

這里的監(jiān)聽器,就是+金幣,+積分,+次數(shù)三個(gè)功能。

事件觸發(fā)就是,【注冊(cè)完畢】這個(gè)事件發(fā)生了,執(zhí)行上述三個(gè)功能。

上述場(chǎng)景在TP6中的實(shí)現(xiàn)方式是:

1. 定義一個(gè)事件register_ok

2. 將指定的類如AfterRegister綁定到register_ok事件,

綁定方法為:在app\event.php中的listen數(shù)組中添加:

return [

? ? 'bind'? ? =>? ? [

? ? ],

? ? 'listen'? =>? ? [

? ? ? ? // 事件名稱為 register_ok,對(duì)應(yīng)的監(jiān)聽類為AfterRegister

? ? ? ? 'register_ok'? ? =>? ? ['app\listener\AfterRegister::class'],

? ? ],

];

3. 當(dāng)register_ok觸發(fā)時(shí),執(zhí)行AfterRegister中的方法(默認(rèn)執(zhí)行handle方法,在handle中去依次執(zhí)行三個(gè)動(dòng)作)

觸發(fā)方式為:Event::trigger('register_ok',$user); 觸發(fā)函數(shù)是可以傳參的,如這里的$user,對(duì)應(yīng)的AfterRegister中的handle方法,也具有對(duì)應(yīng)的形參

class AfterRegister

{

function handle($user){... ...}

}

那么事件監(jiān)聽的實(shí)現(xiàn)方式,跟傳統(tǒng)的函數(shù)調(diào)用有何優(yōu)勢(shì)?

事件使用場(chǎng)景一:

A,B,C三個(gè)人分別負(fù)責(zé)會(huì)員登錄后增加金幣,增加積分,增加登錄次數(shù)記錄的功能書寫。

傳統(tǒng)寫法:

// 注冊(cè)

。。。

// 注冊(cè)完畢增加金幣積分次數(shù)

addGold();?

addScore();?

addTimes();

很顯然,此時(shí)如果三個(gè)人修改同一段代碼必然導(dǎo)致沖突。

使用事件則可以如下方式完成:

①,約定事件名稱為register_ok,分別綁定三個(gè)監(jiān)聽類(目的是將上例中AfterRegister中的handle方法中+金幣+積分+次數(shù)拆開,分別放到AddGold,AddScore,AddTimes的handle函數(shù)中):

return [

? ? 'bind'? ? =>? ? [

? ? ],

? ? 'listen'? =>? ? [

? ? ? ? //? 給register_ok事件,綁定三個(gè)監(jiān)聽類,分別為AddGold,AddScore,AddTimes

? ? ? ? 'register_ok'? ? =>? ? ['app\listener\AddGold::class','app\listener\AddScore::class','app\listener\AddTimes::class']

? ? ],

];

②,在app\listener中加三個(gè)類,分別為AddGold,AddScore,AddTimes

③,在AddGold的handle方法中寫增加金幣的業(yè)務(wù),AddScore的handle方法中寫增加積分的業(yè)務(wù),AddTimes的handle方法中寫增加次數(shù)的業(yè)務(wù)

④,在注冊(cè)代碼的下方,加入事件觸發(fā),即用一個(gè)Event::trigger('register_ok',$user);取代了原本 addGold(); addScore(); addTimes();這種若干個(gè)函數(shù)的寫法。

至此則完成了,N個(gè)監(jiān)聽類去監(jiān)聽一個(gè)事件的功能?;蛟S有人說(shuō),傳統(tǒng)寫法一樣可以用,三個(gè)人分別實(shí)現(xiàn)addGold(); addScore(); addTimes(); 就可以了,那么看下面這個(gè)場(chǎng)景

事件使用場(chǎng)景二:

某系統(tǒng)會(huì)員注冊(cè)成功后,增加金幣。

過(guò)了幾周,要求增加金幣的同時(shí)增加積分。

又過(guò)了幾周,要求增加金幣和積分的同時(shí)增加登錄次數(shù)。

又過(guò)了幾周,要求只增加金幣和登錄次數(shù),不加積分了。

又過(guò)了幾周,要求注冊(cè)成功后增加金幣和登錄次數(shù)的同時(shí),記錄下會(huì)員的登錄IP。

如果是使用傳統(tǒng)方式,需要對(duì)源代碼進(jìn)行不斷的修改和注釋,事件則方便的多,只追加監(jiān)聽器和修改配置文件event.php,而不必改注冊(cè)部分的業(yè)務(wù)代碼??梢?,事件監(jiān)聽的實(shí)現(xiàn)方式,在頻繁出現(xiàn)業(yè)務(wù)變更的地方,有著傳統(tǒng)方式不能比的優(yōu)勢(shì)。

---------------------------------------------------------------------------------------------------

后記:

1. TP6的文檔中給出了事件類event的定義,實(shí)際中幾乎沒有使用的必要,徒增理解成本。

2. 對(duì)于事件的監(jiān)聽也給出了Event::listen的動(dòng)態(tài)綁定方式,遠(yuǎn)不如在event.php中指定,更為方便和靈活可控。

3. 通常我們理解的綁定是 將監(jiān)聽器綁定到事件,這也是JS中的addEventListener的語(yǔ)義,TP6文檔給出的綁定定義則是,將事件名稱綁定到對(duì)應(yīng)的事件類。

4. 基于以上三點(diǎn),個(gè)人推薦采用 event.php配置文件進(jìn)行監(jiān)聽, 用Event::trigger的方式進(jìn)行觸發(fā)事件,而不要用Event::bind和Event::listen。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容