自定義事件
在JS中,消息的通知是通過(guò)事件表達(dá)的,當(dāng)代碼庫(kù)增長(zhǎng)到一定的規(guī)模就需要考慮將行為和自定義事件進(jìn)行解耦,通過(guò)事件機(jī)制可以將類設(shè)計(jì)為獨(dú)立的模塊,通過(guò)事件對(duì)外通信提高了程序的開發(fā)效率。
了解自定義事件的概念:
- 類似 DOM 的行為:你在 DOM 節(jié)點(diǎn)(包括 document 對(duì)象)監(jiān)聽并觸發(fā)自定義事件。這些事件既可以冒泡,也可以被攔截。這正是 Prototype、jQuery 和 MooTools 所做的。如果事件不能擴(kuò)散,就必須在觸發(fā)事件的對(duì)象上進(jìn)行監(jiān)聽。
- 命名空間:一些框架需要你為事件指定命名空間,通常使用一個(gè)點(diǎn)號(hào)前綴來(lái)把你的事件和原生事件區(qū)分開。
- 自定義額外數(shù)據(jù):JavaScript 框架允許你在觸發(fā)自定義事件時(shí),向事件處理器傳送額外的數(shù)據(jù)。jQuery 可以向事件處理器傳遞任意數(shù)量的額外參數(shù)。
- 通用事件 API:只用 Dojo 保留了操作原生 DOM 事件的正常API。而操作自定義事件需要特殊的發(fā)布/訂閱 API。這也意味著 Dojo 中的自定義事件不具有DOM事件的一些行為(比如冒泡)。
- 聲明:我們往往需要在預(yù)定義的事件中加入一些特殊的變化(例如,需要Alt鍵按下才能觸發(fā)的單擊事件),MooTools 運(yùn)行你定義此類自定義事件。此類事件需要預(yù)先聲明,即便你只是聲明他們的名字。任何未聲明的自定義事件不會(huì)被觸發(fā)。
理論太抽象,看看 jQuery 框架中如何使用事件。
jQuery 的事件自定義事件還是通過(guò) on 綁定的,然后再通過(guò) trigger 來(lái)觸發(fā)這個(gè)事件。
//給element綁定hello事件
element.bind("hello",function(){
alert("hello world!");
});
//觸發(fā)hello事件
element.trigger("hello");
這段代碼這樣寫似乎感覺不出它的好處,看了下面的例子也許你會(huì)明白使用自定義事件的好處了,參考右邊的代碼。
trigger需要處理的問(wèn)題
- 模擬事件對(duì)象,用戶模擬處理停止事件冒泡(因?yàn)椴皇峭ㄟ^(guò)瀏覽器系統(tǒng)觸發(fā)的,而是自動(dòng)觸發(fā)的,所以這個(gè)事件對(duì)象要如何處理?)
- 區(qū)分事件類型,觸發(fā)標(biāo)準(zhǔn)的瀏覽器事件 和 自定義事件名綁定的處理程序。
擬冒泡機(jī)制
- 當(dāng)事件是 click 類型,自然是本身支持冒泡這樣的行為,通過(guò) stopPropagation 阻止即可
- 當(dāng)然一些事件,如 focusin 和 blur 本身不冒泡,但 jQuery 為了跨瀏覽器一致性, jQuery 需要在這些事件上模擬了冒泡行為,jQuery 要如何處理?
- 那么如果是自定義的aaa的事件名,又如何處理冒泡?
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
.active{
color: red;
}
</style>
<script src="http://idcbgp.cn/static/lib/jquery/1.9.1/jquery.js" type="text/javascript"></script>
<title>自定義事件</title>
</head>
<body>
<ul id="tabs">
<li data-tab="users">Users</li>
<li data-tab="groups">Groups</li>
</ul>
<div id="tabsContent">
<div data-tab="users">part1</div>
<div data-tab="groups">part2</div>
</div>
<script type="text/javascript">
$.fn.tabs = function(control) {
var element = $(this);
var control = $(control);
element.delegate("li", "click", function() {
var tabName = $(this).attr("data-tab");
//點(diǎn)擊li的時(shí)候觸發(fā)change.tabs自定義事件
element.trigger("change.tabs", tabName);
});
//給element綁定一個(gè)change.tabs自定義事件
element.bind("change.tabs", function(e, tabName) {
element.find("li").removeClass("active");
element.find(">[data-tab='" + tabName + "']").addClass("active");
});
element.bind("change.tabs", function(e, tabName) {
control.find(">[data-tab]").removeClass("active");
control.find(">[data-tab='" + tabName + "']").addClass("active");
});
// 激活第一個(gè)選項(xiàng)卡
var firstName = element.find("li:first").attr("data-tab");
element.trigger("change.tabs", firstName);
return this;
};
$("ul#tabs").tabs("#tabsContent");
</script>
</body>
</html>
請(qǐng)驗(yàn)證,完成請(qǐng)求
由于請(qǐng)求次數(shù)過(guò)多,請(qǐng)先驗(yàn)證,完成再次請(qǐng)求