YUI事件体系之Y.EventTarget

上两篇文章YUI事件体系之Y.Do、YUI事件体系之Y.CustomEvent中,分别介绍了YUI实现AOP的Y.Do对象,以及建立自定义事件机制的Y.CustomEvent对象。

本篇文章,将要介绍YUI事件体系集大成者、最为精华的部分——Y.EventTarget

Y.EventTarget

DOM事件中的目标元素为event.target,这类元素可以触发、监听一些事件,例如input元素的click、focus等事件。这也正是Y.EventTarget的命名渊源,它提供了一种让任意对象定义、监听、触发自定义事件的实现方式。

从设计上看,Y.EventTarget通过内部维护一系列Y.EventCustom对象,提供了可以通过事件名称进行事件定义、监听和触发的便捷接口。另外,推荐使用Y.augment将它以组合的方式加载在其它类上,而不要使用继承。关于Y.augmentY.extend之间的异同,可以参考我之前的一篇文章:Y.extend与Y.augment。

YUI很多基础类都扩展了Y.EventTarget,重要的有Y(YUI instance,sandbox)、Y.GlobalY.NodeY.NodeListY.Base等。

YUILibrary有专门一个章节介绍EventTarget,非常详尽,如果你对EventTarget的设计思路和使用方法感兴趣,请移步YUILibrary-EventTarget。

示例

首先,让我们看看Y.EventTarget独立调用的例子:

// 例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');
});

这种方式实际意义不大,YUI中只有Y.Global使用了这种方式。

下面,让我们看下最广泛的使用方式,即通过Y.augment扩展其它类:

// 例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扩展MyClassY.augment(MyClass, Y.EventTarget);var instance = new MyClass();// 监听addItem事件instance.on('addItem', function (data) {console.log('add an item:', data.item);});// 监听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');
});

源代码分析

接下来,让我们看看YUI的内部实现吧。

注:为了更容易的看懂代码的核心,我做了适当的简化,感兴趣的朋友可以去看未删节的源码。

var AFTER_PREFIX = '~AFTER~';// EventTarget构造器
var ET = function (opts) {var o = opts || {};// 私有事件聚合器this._yuievt = this._yuievt || {id: Y.guid(),events: {},config: o,// 默认配置defaults: {context: o.context || this,host: this,emitFacade: o.emitFacade,fireOnce: o.fireOnce,queuable: o.queuable,broadcast: o.broadcast}};
};ET.prototype = {constructor: ET,// 创建事件publish: function (type, opts) {var ce,events = this._yuievt.events,defaults = this._yuievt.defaults;ce = events[type];if (ce) { // 已创建过该事件if (opts) {ce.applyConfig(opts, true);}} else { // 基于CustomEvent,创建新事件ce = new Y.CustomEvent(type,(opts) ? Y.merge(defaults, opts) : defaults);events[type] = ce;}return ce;},// 监听事件on: function (type, fn, context) {var ce,after,handle,args = null;// 判断是否为后置监听if (type.indexOf(AFTER_PREFIX) > -1) {after = true;type = type.substr(AFTER_PREFIX.length);}// 获取自定义事件对象,如果未创建则先创建ce = this._yuievt.events[type] || this.publish(type);if (arguments.length > 3) {args = Y.Array(arguments, 3, true);}// 调用自定义事件对象的_on方法监听事件handle = ce._on(fn, context, args, after ? 'after' : true);return handle;},// 监听一次事件once: function () {var handle = this.on.apply(this, arguments);if (handle.sub) {// 监听器执行一次则失效handle.sub.once = true;}return handle;},// 后置监听事件after: function (type, fn) {var a = Y.Array(arguments, 0, true);a[0] = AFTER_PREFIX + type;return this.on.apply(this, a);},// 后置监听一次事件onceAfter: function () {var handle = this.after.apply(this, arguments);if (handle.sub) {handle.sub.once = true;}return handle;},// 触发事件fire: function (type) {var ce,args;args = Y.Array(arguments, 1, true);ce = this._yuievt.events[type];// 尚未创建事件if (!ce) return true;return ce.fire.apply(ce, args);},// 注销事件监听detach: function (type, fn, context) {var events = this._yuievt.events,ce,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;}
};

进阶用法

Y.EventTarget作为一个十分重要的类,提供了非常丰富、方便的使用方式,除了依赖内部Y.CustomEvent实现的事件接口、默认执行方法、事件广播等,其余主要有:

a) 事件冒泡

多个EventTarget对象之间可以建立一定事件传播关系,类似DOM事件中的冒泡。

// 例3
YUI().use('event-custom', function (Y) {// 父类function Parent() { ... }Y.augment(Parent, Y.EventTarget, true, null, { emitFacade: true });// 子类function Child() { ... }Y.augment(Child, Y.EventTarget, true, null, { emitFacade: true });var parent = new Parent(),child = new Child();// 子类对象添加冒泡目标对象,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) 事件前缀

在事件冒泡的基础上,考虑到区分不同EventTarget对象触发相同事件,YUI引入了事件前缀(Event Prefix)。

// 例4
YUI().use('event-custom', function (Y) {// 父类function Parent() { ... }Y.augment(Parent, Y.EventTarget, true, null, {emitFacade: true,prefix: 'parent' // 配置事件前缀});// 子类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) { // 要想监听到其它EventTarget对象的see事件,需要设置prefixconsole.log('parent see', e.thing);});child.on('child:see', function (e) { // 等同监听see事件console.log('child see', e.thing);});// output: child hear MM, parent see MMchild.fire('see', { thing: 'MM' });
});

参考

  • YUILibrary-CustomEvent
  • YUILibrary-EventTarget

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477814.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源开放 | DeepKE发布新版本:支持低资源、长篇章、多任务的图谱抽取开源框架(浙江大学)...

OpenKG地址:http://openkg.cn/tool/deepkeGitHub地址:https://github.com/zjunlp/deepkeGitee地址:https://gitee.com/openkg/deepkeDeepKE网站:http://deepke.zjukg.org/CN/index.html开放许可协议:GPL 3.0贡献者&…

LeetCode 478. 在圆内随机生成点(概率)

1. 题目 给定圆的半径和圆心的 x、y 坐标,写一个在圆中产生均匀随机点的函数 randPoint 。 说明: 输入值和输出值都将是浮点数。圆的半径和圆心的 x、y 坐标将作为参数传递给类的构造函数。圆周上的点也认为是在圆中。randPoint 返回一个包含随机点的x坐标和y坐标…

11月AI大事件回顾:GPT3开放使用/女娲视觉大模型/AE文艺复兴/...

编 | iven感谢提供本期内容的 ZenMoore、 jxyxiangyu、付瑶大家好~ 11月的新闻速报来啦!上个月不知道大家有没有忙着写文章,反正小编是这样的:好啦,让我们快来回顾上个月的 AI 大新闻吧!学术进展何恺明 Mas…

开源开放 | 开源立体化漏洞情报知识图谱(四维创智)

OpenKG地址:http://openkg.cn/dataset/vuln-sprocket开放许可协议:CC BY-SA 4.0 (署名相似共享)贡献者:四维创智(李德斌,孙基栩,鲍晨阳)1. 前言随着时间的推移&#xff0…

LeetCode 515. 在每个树行中找最大值(层序遍历)

1. 题目 您需要在二叉树的每一行中找到最大的值。 示例: 输入: 1/ \3 2/ \ \ 5 3 9 输出: [1, 3, 9]来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row 著作…

YUI事件体系之Y.CustomEvent

上一篇文章中,简要介绍了YUI实现AOP的Y.Do对象。 接下来,我们继续对YUI事件体系进行探索。本次要介绍的是Y.CustomEvent对象,从命名上就可以看出,这个对象在整个YUI事件体系中十分重要。它建立起整个自定义事件的体系,…

GBDT是如何成为推荐系统顶级工具人的?

文 | 水哥源 | 知乎Saying1. 集成学习的ensemble注意一定要读作昂三姆包而不是印三姆包,一天一个算法工程师装x小技巧2. 区别bagging和boosting的准则是,先训练的模型对于后训练的模型是否有影响3. GBDT中,B(boosting)…

会议交流 | 如何提升推荐系统的可解释性?——DataFunSummit2022知识图谱在线峰会...

背景介绍知识图谱及特征学习结合智能推荐,可解决数据稀疏性及冷启动问题,更好的提升推荐决策场的准确性、多样性及可解释性,进而提升各个场景的推荐决策效率和体验。3月12日13:30-16:50,在DataFunSummit2022:知识图谱在…

LeetCode 143. 重排链表(链表反转+快慢指针)

1. 题目 给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 示例 1: 给定链表 1->2->3->4, 重新排列为…

YUI事件体系之Y.Do

YUI团队在种种场合不断的夸耀自己的事件体系是多么强大: YUI 3′s Event module is one of the strengths of the library –Eric Miraglia, YUI Theater — Luke Smith: “Events Evolved”YUI 3 is not all about DOM manipulation — it also contains a robust …

论文浅尝 | 采用成对编码的图卷积网络用于知识图谱补全

笔记整理:姚祯,浙江大学在读硕士,研究方向为知识图谱表示学习,图神经网络。论文引用:Liu S, Grau B, Horrocks I, et al. INDIGO: GNN-based inductive knowledge graph completion using pair-wise encoding[J]. Adva…

调研了下 AI 作曲,顺便做了期视频...快进来听歌!

文 | 白鹡鸰编 | 小轶视频 | 白鹡鸰嗨,大家好!这里是卖萌屋,我是白鹡鸰。今天和大家聊聊人工智能作曲。人工智能在音乐领域的应用已经非常常见了,像听歌识曲、曲风分类、自动扒谱等等,而 利用机器来替代人类作曲 &…

LeetCode 1275. 找出井字棋的获胜者(位运算)

1. 题目 A 和 B 在一个 3 x 3 的网格上玩井字棋。 井字棋游戏的规则如下: 玩家轮流将棋子放在空方格 (" ") 上。第一个玩家 A 总是用 “X” 作为棋子,而第二个玩家 B 总是用 “O” 作为棋子。“X” 和 “O” 只能放在空方格中,而…

论文浅尝 | DSKReG:基于关系GNN的推荐知识图谱可微抽样

笔记整理:李爽,天津大学硕士链接:https://dl.acm.org/doi/pdf/10.1145/3459637.3482092动机在信息爆炸的时代,推荐系统被广泛研究和应用,以发现用户的偏好信息。RS在冷启动时性能较差,如果将知识图谱(Knowl…

改变世界,改善生活:我从科沃斯扫地机器人X1,看到了AI新的希望

深度学习是当代人工智能的核心,计算机视觉、语音、NLP则是当代人工智能落地的热门应用方向。然而,机器人、智能agent这种看起来更加“人工智能”的话题却在大众视野出现的越来越少,取而代之的热点讨论反而是看似与人工智能关联不是那么直接的…

数据开放平台的配置管理

背景 美团是数据驱动的技术公司, 非常重视使用数据的效率。为了达到这个目标,我们将数据以开放平台的形式开放给需求方。例如,帮助需求方开发报表的报表开放平台,帮助需求方获取数据的自助查询平台,让需求方参与数据建…

LeetCode 1271. 十六进制魔术数字(进制转换)

1. 题目 你有一个十进制数字,请按照此规则将它变成「十六进制魔术数字」:首先将它变成字母大写的十六进制字符串,然后将所有的数字 0 变成字母 O ,将数字 1 变成字母 I 。 如果一个数字在转换后只包含 {“A”, “B”, “C”, “…

评测任务征集 | 全国知识图谱与语义计算大会(CCKS 2022)

评测任务征集全国知识图谱与语义计算大会(CCKS 2022)2022年8月25-28日,秦皇岛http://sigkg.cn/ccks2022/全国知识图谱与语义计算大会(CCKS: China Conference on Knowledge Graph and SemanticComputing)由中国中文信息…

SegmentFault 美团云采访实录

约半年前,美团悄然上线了美团云(Meituan Open Services,简称MOS),这是美团网根据自身虚拟化平台开发和运维经验开放的云计算服务,类似AWS。 美团 CEO 王兴可能是中国最知名的连续创业者,曾创办校…

开局一段扯,数据全靠编?真被一篇“神论文”气到了

文 | 苏剑林(追一科技)编 | 智商掉了一地看来以后我们看论文的时候,不仅要关心论文成绩的可复现性,还要留意它们的求和、均值、方差等有没有算错,否则真的是“无奇不有”!!这篇文章谈一下笔者被…