第一種方式:使用JavaScript原生提供的CustomEvent創(chuàng)建自定義事件
比如可以這樣創(chuàng)建:
var evt = new CustomEvent(type, {detail: msg, bubbles: true, cancelable: true});
然后監(jiān)聽(tīng)并觸發(fā)某個(gè)自定義事件
element.addEventListener('longpress', longpressFn);
element.dispatchEvent(evt);
第二種方式:自己模擬一個(gè)自定義事件發(fā)布訂閱對(duì)象
var Event = (function() {
var clientList = {};
var listen,
trigger,
remove;
listen = function(key, fn) {
if (!clientList[key]) {
clientList[key] = [];
}
clientList[key].push(fn);
};
trigger = function() {
var key = [].shift.call(arguments);
var fns = clientList[key];
if (!fns || fns.length === 0) {
return false;
}
for (var i = 0, fn; fn = fns[i++];) {
fn.apply(this, arguments);
}
};
remove = function(key, fn) {
var fns = clientList[key];
// key對(duì)應(yīng)的消息沒(méi)有被人訂閱
if (!fns) {
return false;
}
// 沒(méi)有傳入fn(具體的回調(diào)函數(shù)), 表示取消key對(duì)應(yīng)的所有訂閱
if (!fn) {
fns && (fns.length = 0);
}
else {
// 反向遍歷
for (var i = fns.length - 1,_fn=fns[i]; i >= 0; i--) {
if (_fn === fn) {
// 刪除訂閱回調(diào)函數(shù)
fns.splice(i, 1);
}
}
}
};
return {
listen: listen,
trigger: trigger,
remove: remove
}
}());
這兩種方式都能實(shí)現(xiàn)一個(gè)自定義事件的創(chuàng)建、監(jiān)聽(tīng)、觸發(fā)、刪除,但區(qū)別是第一種是原生DOM提供的API,第二種是用發(fā)布訂閱模式去模擬的?原生DOM的創(chuàng)建方式也是一種發(fā)布訂閱模式么?
那在實(shí)際項(xiàng)目中用哪種比較好?查了下資料,發(fā)現(xiàn)用原生DOM的API貌似有IE方面的兼容問(wèn)題
現(xiàn)在一些大型的庫(kù)或者框架都是用第二種那樣自己實(shí)現(xiàn)的自定義事件訂閱系統(tǒng)么?(主要最近在造自己的輪子,聽(tīng)說(shuō)這種模式可以降低代碼的耦合度,想學(xué)習(xí)下。。)
你的訂閱發(fā)布確定沒(méi)問(wèn)題么?我理解的,訂閱發(fā)布結(jié)合面相對(duì)象來(lái)說(shuō),最簡(jiǎn)單的模式應(yīng)該是至少有三部分:
發(fā)布消息者,消息本身,和訂閱者。
原生dom的事件模式中,其實(shí)本身也就是一個(gè)訂閱發(fā)布模式。
1.每個(gè)htmlElement類(lèi)最基礎(chǔ)的interface,都是eventTarget,也就是"發(fā)布消息者"。這個(gè)你可以看mdn:這里。
也就是說(shuō),HTMLElement有個(gè)繼承鏈,Element---Node---EventTarget。EvetntTarget接口實(shí)現(xiàn)了發(fā)送消息的方法,所以,原生dom元素可以發(fā)送消息,也就是說(shuō),dom元素可以作為"發(fā)布消息者"。
2.每次事件發(fā)送的消息本身,其實(shí)按照面相對(duì)象來(lái)說(shuō),每次事件就是一個(gè)Event類(lèi)的實(shí)例,每次有事件觸發(fā),都會(huì)創(chuàng)建一個(gè)消息Event實(shí)例,由發(fā)布消息者,也就是指定的dom元素,廣播給訂閱者。
3.dom模型中的訂閱者,其實(shí)可以簡(jiǎn)單理解成就是我們注冊(cè)好的"事件處理函數(shù)"。然而,實(shí)際上,按照dom標(biāo)準(zhǔn),dom事件訂閱者也是有個(gè)interface格式的:這里。滿(mǎn)足了這個(gè)格式,就可以給eventTarget添加listener。每次有Event發(fā)出,不管你是自定義事件還是真的用戶(hù)交互事件,都會(huì)觸發(fā)listener。
你自己實(shí)現(xiàn)的那個(gè),并沒(méi)有抽象出這三個(gè)部分吧。當(dāng)然,訂閱發(fā)布完全可以自己訂閱自己,消息也只在內(nèi)部不暴露。只是感覺(jué)這樣就很模糊了。
其實(shí),你自己實(shí)現(xiàn)的訂閱發(fā)布,每個(gè)接口原生JS的HTMLElement上都有了。只看最新的,你自己實(shí)現(xiàn)的那個(gè)listen方法,就是addEventListener;trigger方法,就是dispatchEvent;remove就是removeEventListener。而且你自己實(shí)現(xiàn)的那個(gè)并沒(méi)有抽象出Event消息和訂閱者。
呃,題主連設(shè)計(jì)模式和 API 的關(guān)系都沒(méi)搞清就要開(kāi)始造輪子了么……
這兩者的關(guān)系就是沒(méi)有關(guān)系。設(shè)計(jì)模式是設(shè)計(jì)模式,任何語(yǔ)言任何 API,想用就用,它是“可復(fù)用面向?qū)ο筌浖幕A(chǔ)”。瀏覽器 DOM 事件機(jī)制是“訂閱模式”的一種實(shí)現(xiàn),你想自己實(shí)現(xiàn)一個(gè)訂閱模式當(dāng)然沒(méi)問(wèn)題(不過(guò)多半是觀(guān)察者模式)。
建議題主先把《設(shè)計(jì)模式》那本書(shū)好好看一遍。
北大青鳥(niǎo)APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專(zhuān)業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開(kāi)發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_(kāi)發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開(kāi)發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開(kāi)發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開(kāi)發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問(wèn),美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。