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 set of class/object management tools, not to mention our powerful custom events –Tilo Mitra, 10 Things I Learned While Interning at YUI
  • One of the strengths of the YUI App Framework is that it’s integrated tightly with the rest of YUI and benefits from YUI’s fantastic event system and plugin/extension infrastructure. –Ryan Grove, How can I decided whether to choose YUI 3’s MVC or Backbone for a new project?

事实的确如此吗?就使用YUI的开发者反馈来看,应该是不错的:

  • AFAIK YUI 3’s event system is the most sophisticated of any JavaScript framework. Am I wrong in thinking that? –Walter Rumsby
  • I love the event system in YUI. Pure awesomeness. –Kevin Isom
  • I am constantly impressed by the degree of excellence I find in working with the YUI3 framework –Andrew Wooldridge, Cross YUI Communication and Custom Events

作为一名YUI用户,我对其事件体系的强大深有体会。从本篇文章起,我将对YUI事件机制做一个全面分析。

本次我们介绍的是比较基础的两个对象Y.EventHandleY.Do。千里之行积于跬步,YUI整套事件机制也是从这两个对象开始构筑的。

Y.EventHandle

Y.EventHandle的作用很简单:注销事件/消息监听。

Y.EventHandle = function (evt, sub) {this.evt = evt; // 事件对象this.sub = sub; // 监听对象
};
Y.EventHandle.detach = function () {this.evt._delete(this.sub); // 执行event对象的_delete方法,注销事件/消息监听return true;
};

Y.Do

Y.Do的作用是:向对象方法前面或者后面插入其它方法(前置、后置方法),以达到动态修改对象行为的目的。这种方式,也称作AOP。

示例

让我们先来看个简单的例子:

// 例1
YUI().use('event-custom', function (Y) {var cat = {eat: function () {console.log('eat a fish');}};cat.eat(); // output: eat a fishvar beforeHandle = Y.Do.before(function () {console.log('catch a fish');}, cat, 'eat');var afterHandle = Y.Do.after(function () {console.log('done!');}, cat, 'eat');cat.eat(); // output: catch a fish, eat, done!afterHandle.detach();cat.eat(); // output: catch a fish, eat
});

在不修改原对象方法的基础上,可以方便的添加前置、后置方法,并且注销这些方法也很容易。Y.Do非常漂亮的解决了我们动态修改对象方法的需求!很难想象,如果不用Y.Do代码会复杂成怎样。

源代码分析

接下来,让我们看看YUI的内部实现吧。这是多么有趣的事,就像小时候买把手枪,想不明白为什么可以射击,就砸开一看究竟。

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

// 代码版本为YUI3.4.1,YUI3.5.0对Y.Do的实现有所改进
var DO_BEFORE = 0,DO_AFTER = 1;
Y.Do = {// 缓存处理对象objs: {},before: function (fn, obj, sFn) {return this._inject(DO_BEFORE, fn, obj, sFn);},after: function (fn, obj, sFn) {return this._inject(DO_AFTER, fn, obj, sFn);},_inject: function (when, fn, obj, sFn) {var id = Y.stamp(obj), o, sid;if (!this.objs[id]) this.objs[id] = {};o = this.objs[id];if (!o[sFn]) {// 创建保存对象、方法名的Method对象o[sFn] = new Y.Do.Method(obj, sFn);// 修改对象方法obj[sFn] = function () {return o[sFn].exec.apply(o[sFn], arguments);};}sid = id + Y.stamp(fn) + sFn;// 注册插入方法o[sFn].register(sid, fn, when);// 返回EventHandle对象,方便注销return new Y.EventHandle(o[sFn], sid);}
}Y.Do.Method = function (obj, sFn) {this.obj = obj;this.methodName = sFn;this.method = obj[sFn];this.before = {};this.after = {};
};
Y.Do.Method.prototype.register = function (sid, fn, when) {if (when) {this.after[sid] = fn;} else {this.before[sid] = fn;}
};
// 注销插入方法
Y.Do.Method.prototype._delete = function (sid) {delete this.before[sid];delete this.after[sid];
};
Y.Do.Method.prototype.exec = function () {var before = this.before,after = this.after,i, ret;// 执行插入前面的方法for (i in before) {if (before.hasOwnProperty(i)) {ret = before[i].apply(this.obj, arguments);}}// 执行原方法ret = this.method.apply(this.obj, arguments);// 执行插入后面的方法for (i in after) {if (after.hasOwnProperty(i)) {ret = after[i].apply(this.obj, arguments);}}return ret;
};

适用场景

a) 动态修改对象方法

请参照例1。

b) 动态修改原型方法

原型也是对象,所以,另外一个适用场景就是修改原型方法。

// 例2
YUI().use('event-custom', function (Y) {function Car(brand) {this.brand = brand;};Car.prototype.start = function () {console.log('start');};var myCar = new Car('bmw');Y.Do.before(function () {console.log('open the door');}, Car.prototype, 'start');Y.Do.after(function () {console.log('the car is started!');}, Car.prototype, 'start');myCar.start(); // output: open the door, start, the car is started!
});

c) 动态修改宿主方法

为宿主对象添加插件时,插件往往需要在宿主一些方法前后执行某些操作。YUI提供了一个很好的例子。

d) 动态修改被扩展对象方法

为对象添加扩展时,扩展对象往往需要在被扩展对象一些方法前后执行某些操作。YUI提供了一个很好的例子。

进阶使用

由于简化代码,省略了一些细节。Y.Do还有很多功能,例如:可以根据前置方法返回值阻止默认方法执行、替换参数等等。下面介绍一些这样的进阶使用方式:

// 例3
YUI().use('event-custom', function (Y) {function Car(brand, degree) {this.brand = brand;this.degree = degree || 0;};Car.prototype.shift = function (degree) {console.log('change to ' + degree);};var myCar = new Car('bmw');// 多个前置方法Y.Do.before(function (degree) {console.log('prepare to change');}, Car.prototype, 'shift');Y.Do.before(function (degree) {console.log('prepare to change again');}, Car.prototype, 'shift');myCar.shift(1); // output: prepare to change, prepare to change again, change to 1// 多个后置方法Y.Do.after(function (degree) {console.log('already change');}, Car.prototype, 'shift');Y.Do.after(function (degree) {console.log('already change again');}, Car.prototype, 'shift');myCar.shift(2); // output: ..., change to 2, already change, already change again // 中止执行Y.Do.before(function (degree) {if (degree < 0) {console.log('halt, too low!');return new Y.Do.Halt();}}, Car.prototype, 'shift');myCar.shift(-1); // output: ..., halt, too low! // 阻止默认方法Y.Do.before(function (degree) {if (degree > 4) {console.log('prevent changing, too high!');return new Y.Do.Prevent();}}, Car.prototype, 'shift');myCar.shift(5); // output: ..., prevent changing, too high!, already change, ... // 替换参数Y.Do.before(function (degree) {var d = Math.floor(degree);if (degree !== d) {return new Y.Do.AlterArgs('degree should be a integer', [d]);}}, Car.prototype, 'shift');myCar.shift(2.5); // output: ..., change to 2, ... // 替换返回值Y.Do.after(function (degree) {if (degree === 0) {return new Y.Do.AlterReturn('', 'wow, your car now has no power');}}, Car.prototype, 'shift');var ret = myCar.shift(0); // output: ..., change to 0, ... console.log(ret); // wow, your car now has no power
});

参考

  • YUILibrary-Do
  • YUILibrary-EventTarget
  • Wikipedia-AOP

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

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

相关文章

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

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

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

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

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

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

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

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

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

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

数据开放平台的配置管理

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

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

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

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

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

SegmentFault 美团云采访实录

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

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

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

LeetCode 147. 对链表进行插入排序(链表)

1. 题目 对链表进行插入排序。 插入排序的动画演示如上。从第一个元素开始&#xff0c;该链表可以被认为已经部分排序&#xff08;用黑色表示&#xff09;。 每次迭代时&#xff0c;从输入数据中移除一个元素&#xff08;用红色表示&#xff09;&#xff0c;并原地将其插入到…

征稿 | 软件学报专刊征文:知识赋能的信息系统

伴随着人工智能的浪潮&#xff0c;智慧信息系统的发展方兴未艾&#xff0c;正处于由感知智能到认知智能转变的关键时期。要实现认知智能的系统跃升&#xff0c;离不开知识的赋能。在数字化转型背景下&#xff0c;数据对象和交互方式的日益丰富和变化&#xff0c;对以知识图谱为…

基于Flume的美团日志收集系统(二)改进和优化

在《基于Flume的美团日志收集系统(一)架构和设计》中&#xff0c;我们详述了基于Flume的美团日志收集系统的架构设计&#xff0c;以及为什么做这样的设计。在本节中&#xff0c;我们将会讲述在实际部署和使用过程中遇到的问题&#xff0c;对Flume的功能改进和对系统做的优化。 …

LeetCode 462. 最少移动次数使数组元素相等 II(数学)

1. 题目 给定一个非空整数数组&#xff0c;找到使所有数组元素相等所需的最小移动数&#xff0c;其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。 例如: 输入: [1,2,3] 输出: 2说明&#xff1a; 只有两个动作是必要的&#xff08;记得每一步仅可…

embedding亦福亦祸?XGBoost与LightGBM的新机遇

文 | 水哥源 | 知乎Saying1. 小的性能差异在容易实现面前一文不值&#xff0c;这一点是XGBoost和LightGBM的最大优势2. 没能与embedding很好地结合无疑是树模型的灾难&#xff0c;吃不下巨量的新数据&#xff0c;也打不过DNN&#xff0c;除了一些规模比较小的公司&#xff0c;树…

论文浅尝 - ACL2022 | 面向推理阅读理解的神经符号方法

转载公众号 | 南大Websoft概述近两年来NLP领域出现了一些富有挑战性的机器阅读理解数据集&#xff0c;如ReClor和LogiQA。这两个数据集中的问题需要对文本进行逻辑推理&#xff0c;然而传统的神经模型不足以进行逻辑推理&#xff0c;传统的符号推理器不能直接应用于文本。为了应…

美团数据仓库的演进

美团数据仓库&#xff0c;在过去的两年中&#xff0c;与我们的业务一起高速发展。在这一演进过程中&#xff0c;有很多值得总结和沉淀的内容。这篇文档回顾下美团数据仓库这两年发展过程中遇到的各种问题&#xff0c;为什么选择了现在的技术方案&#xff0c;每一个功能和模块是…

LeetCode 1026. 节点与其祖先之间的最大差值(二叉树DFS)

1. 题目 给定二叉树的根节点 root&#xff0c;找出存在于不同节点 A 和 B 之间的最大值 V&#xff0c;其中 V |A.val - B.val|&#xff0c;且 A 是 B 的祖先。 &#xff08;如果 A 的任何子节点之一为 B&#xff0c;或者 A 的任何子节点是 B 的祖先&#xff0c;那么我们认为…

凭“难听”上热搜的 idol 们,不如考虑下让 Transformer 帮您作曲?

视频制作 | 白鹡鸰编 | 小轶考虑到 “AI 音乐”这一主题的特殊性&#xff0c;唯有多媒体的视频形式才能更好地给大家带来视听上的多重感受。于是&#xff0c;小屋的白鸟鸟同学在科研间隙连续肝了好几个晚上&#xff0c;才得以完成这次视频。然而在上周的推送中&#xff0c;不知…

YUI3在美团的实践

美团网在2010年引爆了团购行业&#xff0c;并在2012年销售额超过55亿&#xff0c;实现了全面盈利。在业务规模不断增长的背后&#xff0c;作为研发队伍中和用户最接近的前端团队承担着非常大的压力&#xff0c;比如用户量急剧上升带来的产品多样化&#xff0c;业务运营系统的界…