日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

YUI事件体系之Y.EventTarget

發(fā)布時(shí)間:2024/7/5 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 YUI事件体系之Y.EventTarget 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上兩篇文章YUI事件體系之Y.Do、YUI事件體系之Y.CustomEvent中,分別介紹了YUI實(shí)現(xiàn)AOP的Y.Do對(duì)象,以及建立自定義事件機(jī)制的Y.CustomEvent對(duì)象。

本篇文章,將要介紹YUI事件體系集大成者、最為精華的部分——Y.EventTarget。

Y.EventTarget

DOM事件中的目標(biāo)元素為event.target,這類(lèi)元素可以觸發(fā)、監(jiān)聽(tīng)一些事件,例如input元素的click、focus等事件。這也正是Y.EventTarget的命名淵源,它提供了一種讓任意對(duì)象定義、監(jiān)聽(tīng)、觸發(fā)自定義事件的實(shí)現(xiàn)方式。

從設(shè)計(jì)上看,Y.EventTarget通過(guò)內(nèi)部維護(hù)一系列Y.EventCustom對(duì)象,提供了可以通過(guò)事件名稱(chēng)進(jìn)行事件定義、監(jiān)聽(tīng)和觸發(fā)的便捷接口。另外,推薦使用Y.augment將它以組合的方式加載在其它類(lèi)上,而不要使用繼承。關(guān)于Y.augment和Y.extend之間的異同,可以參考我之前的一篇文章:Y.extend與Y.augment。

YUI很多基礎(chǔ)類(lèi)都擴(kuò)展了Y.EventTarget,重要的有Y(YUI instance,sandbox)、Y.Global、Y.Node、Y.NodeList、Y.Base等。

YUILibrary有專(zhuān)門(mén)一個(gè)章節(jié)介紹EventTarget,非常詳盡,如果你對(duì)EventTarget的設(shè)計(jì)思路和使用方法感興趣,請(qǐng)移步Y(jié)UILibrary-EventTarget。

示例

首先,讓我們看看Y.EventTarget獨(dú)立調(diào)用的例子:

// 例1 YUI().use('event-custom', function (Y) {var et = new Y.EventTarget();et.on('say', function (msg) {console.log('say:', msg);});et.on('listen', function (msg) {console.log('listen:', msg);});// output: say: Hello, worldinstance.fire('say', 'Hello, world'); });

這種方式實(shí)際意義不大,YUI中只有Y.Global使用了這種方式。

下面,讓我們看下最廣泛的使用方式,即通過(guò)Y.augment擴(kuò)展其它類(lèi):

// 例2 YUI().use('event-custom', function (Y) {function MyClass() {}MyClass.prototype.add = function (item) {// do sththis.fire('addItem', { item: item });};MyClass.prototype.remove = function (item) {// do sththis.fire('removeItem', { item: item });};// 用EventTarget擴(kuò)展MyClassY.augment(MyClass, Y.EventTarget);var instance = new MyClass();// 監(jiān)聽(tīng)addItem事件instance.on('addItem', function (data) {console.log('add an item:', data.item);});// 監(jiān)聽(tīng)removeItem事件instance.on('removeItem', function (data) {console.log('remove an item:', data.item);});// output: add an item: orangeinstance.add('orange');// output: remove an item: redinstance.remove('red'); });

源代碼分析

接下來(lái),讓我們看看YUI的內(nèi)部實(shí)現(xiàn)吧。

注:為了更容易的看懂代碼的核心,我做了適當(dāng)?shù)暮?jiǎn)化,感興趣的朋友可以去看未刪節(jié)的源碼。

var AFTER_PREFIX = '~AFTER~';// EventTarget構(gòu)造器 var ET = function (opts) {var o = opts || {};// 私有事件聚合器this._yuievt = this._yuievt || {id: Y.guid(),events: {},config: o,// 默認(rèn)配置defaults: {context: o.context || this,host: this,emitFacade: o.emitFacade,fireOnce: o.fireOnce,queuable: o.queuable,broadcast: o.broadcast}}; };ET.prototype = {constructor: ET,// 創(chuàng)建事件publish: function (type, opts) {var ce,events = this._yuievt.events,defaults = this._yuievt.defaults;ce = events[type];if (ce) { // 已創(chuàng)建過(guò)該事件if (opts) {ce.applyConfig(opts, true);}} else { // 基于CustomEvent,創(chuàng)建新事件ce = new Y.CustomEvent(type,(opts) ? Y.merge(defaults, opts) : defaults);events[type] = ce;}return ce;},// 監(jiān)聽(tīng)事件on: function (type, fn, context) {var ce,after,handle,args = null;// 判斷是否為后置監(jiān)聽(tīng)if (type.indexOf(AFTER_PREFIX) > -1) {after = true;type = type.substr(AFTER_PREFIX.length);}// 獲取自定義事件對(duì)象,如果未創(chuàng)建則先創(chuàng)建ce = this._yuievt.events[type] || this.publish(type);if (arguments.length > 3) {args = Y.Array(arguments, 3, true);}// 調(diào)用自定義事件對(duì)象的_on方法監(jiān)聽(tīng)事件handle = ce._on(fn, context, args, after ? 'after' : true);return handle;},// 監(jiān)聽(tīng)一次事件once: function () {var handle = this.on.apply(this, arguments);if (handle.sub) {// 監(jiān)聽(tīng)器執(zhí)行一次則失效handle.sub.once = true;}return handle;},// 后置監(jiān)聽(tīng)事件after: function (type, fn) {var a = Y.Array(arguments, 0, true);a[0] = AFTER_PREFIX + type;return this.on.apply(this, a);},// 后置監(jiān)聽(tīng)一次事件onceAfter: function () {var handle = this.after.apply(this, arguments);if (handle.sub) {handle.sub.once = true;}return handle;},// 觸發(fā)事件fire: function (type) {var ce,args;args = Y.Array(arguments, 1, true);ce = this._yuievt.events[type];// 尚未創(chuàng)建事件if (!ce) return true;return ce.fire.apply(ce, args);},// 注銷(xiāo)事件監(jiān)聽(tīng)detach: function (type, fn, context) {var events = this._yuievt.events,ce,i;// 未設(shè)置事件類(lèi)型,則注銷(xiāo)所有類(lèi)型的事件if (!type) {for (i in events) {if (events.hasOwnProperty(i)) {events[i].detach(fn, context);}}return this;}ce = events[type];if (ce) {ce.detach(fn, context);}return this;} };

進(jìn)階用法

Y.EventTarget作為一個(gè)十分重要的類(lèi),提供了非常豐富、方便的使用方式,除了依賴(lài)內(nèi)部Y.CustomEvent實(shí)現(xiàn)的事件接口、默認(rèn)執(zhí)行方法、事件廣播等,其余主要有:

a) 事件冒泡

多個(gè)EventTarget對(duì)象之間可以建立一定事件傳播關(guān)系,類(lèi)似DOM事件中的冒泡。

// 例3 YUI().use('event-custom', function (Y) {// 父類(lèi)function Parent() { ... }Y.augment(Parent, Y.EventTarget, true, null, { emitFacade: true });// 子類(lèi)function Child() { ... }Y.augment(Child, Y.EventTarget, true, null, { emitFacade: true });var parent = new Parent(),child = new Child();// 子類(lèi)對(duì)象添加冒泡目標(biāo)對(duì)象,child -> parentchild.addTarget(parent);parent.on('hear', function (e) {console.log('parent hear', e.msg);});child.on('hear', function (e) {console.log('child hear', e.msg);});// output: child hear Hi, parent hear Hichild.fire('hear', { msg: 'Hi' }); });

b) 事件前綴

在事件冒泡的基礎(chǔ)上,考慮到區(qū)分不同EventTarget對(duì)象觸發(fā)相同事件,YUI引入了事件前綴(Event Prefix)。

// 例4 YUI().use('event-custom', function (Y) {// 父類(lèi)function Parent() { ... }Y.augment(Parent, Y.EventTarget, true, null, {emitFacade: true,prefix: 'parent' // 配置事件前綴});// 子類(lèi)function Child() { ... }Y.augment(Child, Y.EventTarget, true, null, {emitFacade: true,prefix: 'child' // 配置事件前綴});var parent = new Parent(),child = new Child();child.addTarget(parent);parent.on('hear', function (e) { // 不能捕捉到child的hear事件console.log('parent hear', e.msg);});child.on('hear', function (e) {console.log('child hear', e.msg);});// output: child hear Hichild.fire('hear', { msg: 'Hi' });parent.on('*:see', function (e) { // 要想監(jiān)聽(tīng)到其它EventTarget對(duì)象的see事件,需要設(shè)置prefixconsole.log('parent see', e.thing);});child.on('child:see', function (e) { // 等同監(jiān)聽(tīng)see事件console.log('child see', e.thing);});// output: child hear MM, parent see MMchild.fire('see', { thing: 'MM' }); });

參考

  • YUILibrary-CustomEvent
  • YUILibrary-EventTarget

總結(jié)

以上是生活随笔為你收集整理的YUI事件体系之Y.EventTarget的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。