事件选择器对决

发布日期: 作者:

简单挑战:找到两个不同元素(使用它们的 #ID 作为引用)下面的所有 LI 元素,并绑定一个点击处理程序,该处理程序会更改 LI 的文本颜色。以下是您在所有流行的事件/选择器库中执行此操作的方式。

Behaviour + Prototype

Behaviour.register({
  '#item li': function(element) {
    Event.observe(element, 'click', function(event) {
      Event.element(element).setStyle({color: '#c00'});
    });
  },
    
  '#otheritem li': function(element) {
    Event.observe(element, 'click', function(event) {
      Event.element(element).setStyle({color: '#c00'});
    });
  }
});

Prototype 1.5.0

$$('#item li, #otheritem li').each(function(li){
  Event.observe(li, 'click', function(event) {
    Event.element(li).setStyle({color: '#c00'});
  });
});

event:Selectors

EventSelectors.start({
  '#item li:click, #otheritem li:click': function(){
    this.setStyle({'color': '#c00'});
  }
});

jQuery

$("#item li, #otheritem li").click(function(){
  $(this).css('color', '#c00');
});

我喜欢认为代码本身说明了一切,哪个最容易使用和理解。我发现有趣的是,Prototype 正迁移到更接近 jQuery 的东西,而 jQuery 本身正在推出一些非常酷的新东西。一定要密切关注新版本的发布,它们很快就会推出。

关于“事件选择器对决”的 31 则评论

  1. 哇,JQ 的解决方案是迄今为止最明显的选择。我最近才开始深入研究它,此前看到了 Cody 最近使用 Thickbox 做了什么。我对它简洁和逻辑的印象非常深刻,并且期待着新版本的发布。

  2. 几个快速问题
    1. 我找不到可以在命令行使用的 svn url(svn co ...),这是故意的吗?也许你可以提供一个。
    2. 是否可以有一个更开放的论坛......一个我不需要订阅的论坛?我收到的电子邮件已经够多了,我只偶尔需要互动,订阅似乎很愚蠢......也许 Google Groups 是一个不错的选择。
    3. 下一个版本什么时候发布?我在 svn(web)中看到了一些拖放代码,也许可以写一篇关于预期内容的文章?
    4. 这可能适合论坛(见 #2)。有没有办法查询 DOM,并将结果以树的形式而不是数组的形式返回?我有一堆嵌套的 div、表格等,它们代表类似于解析树的东西,我需要从这些树中构建表达式,如果我得到一个扁平化的节点集,这将不容易(不可能?)。

    顺便说一句,这看起来真的很酷 :)

  3. 嗨,John,

    这项工作和 JQuery 本身做得很好。API 很棒。

    我有一些关于 JQuery 的建设性意见。我想更多地探索 jQuery,但有一件事让我对它很反感,那就是代码的简洁性。像 a、b、c 这样的变量名没有意义,这使得 jQuery 的代码很难阅读和理解。

    我假设这是一个文件大小决定,但我们有压缩工具来处理此类问题。虽然我当然可以阅读 jQuery 文档来解决使用方法,但为了更深入地理解代码本身,我们必须能够阅读它。

    另外,关于你所做的选择器方面的内容。我想指出,你也可以使用 event:Selectors 访问事件对象,并且你还可以使用 'this' 关键字访问上下文中的对象。最后,使用 event:Selectors,你可以在每个规则中使用多个事件类型(例如,#item:click, #item2:mouseover: function(e) {} ...)。

  4. 嗨,Justin - 很高兴看到你来!

    关于变量命名问题的观点很棒。使用短变量名已经成为我代码编写习惯的“根深蒂固”的一部分,我绝对需要改变它。

    关于 'this' 关键字的观点很好,我现在已经将你的代码改用它,而不是 'e' 参数。绑定多个事件类型绝对是 event:Selctors 的一大优势,感谢你提到了这一点。

  5. 这可能看起来很奇怪,但我同时是 JQuery 和 Prototype/Scriptaculous 的忠实粉丝,但它们之间在 API 上竞争是否有意义?例如,为什么你不为 Prototype 贡献代码,反之亦然?或者,一开始......在 Rails 中包含 JQuery:defaults?我是不是漏掉了什么?这些库开始成为开发中的真正规范,每个人都在寻找解决像这样的简单问题的终极单行代码......无论如何,做得很好!

  6. Jon - 感谢你的反馈!Prototype 和 Scriptaculous 都是很棒的库,包含大量宝贵的优秀代码 - 但它们都有一些 jQuery 没有关注的东西

    1) 它们是为特定目的而编写的(例如,Prototype 是为了与 Ruby on Rails 很好地协同工作而编写的,Scriptaculous 是为了很好地实现效果而编写的) - 并且在处理新的输入时非常防御。
    2) 它们的功能非常强大(因此,下载文件很大)。

    最重要的是,我们希望 jQuery 成为最简单的库,同时仍然具有最大的“影响力”。因此,与其提供几十种晦涩的动画(例如),我们只提供少量动画,但将 API 保持开放,以便将来进行改进/插件开发。

    因此,要回答你的问题:我们当然会考虑向 Prototype 和/或 Scriptaculous 提交一些内容 - 但目前,我们主要关注的是保持这个库简洁而美观,并修复出现的所有错误:-)。

  7. 嗨,John,

    我真正希望看到的是对 :hover 事件的类似比较。

    当我找到 JQuery 时,我就不再关注 Prototype 和 Dojo 了(或者至少直到我需要做更重的东西)——所以他们可能也有这个——但我喜欢你对 hover 的实现,它处理了所有嵌套和冒泡......只是有效。

    能够仅用 3-4 行代码将 JQuery 应用到Suckerfish Dropdowns(或任何需要 *:hover 才能在 IE 中工作的代码)对我来说是一个胜利,我认为它将再次证明你的观点。

  8. Pingback: La potencia de JQuery » ingeniuz :: desarrollo web útil

  9. Pingback: Event Selector Showdown

  10. 这很酷。但值得一提的是:代表 YUI 团队
    YAHOO.util.Event.on([YAHOO.util.Dom.get('item').getElementsByTagName('li'),
    YAHOO.util.Dom.get('otheritem').getElementsByTagName('li')],
    'click',function(){ YAHOO.util.Dom.setStyle(this,'color','#c00'); });};

    考虑到 YUI 不是一个事件选择器库,这已经很不错了。yQuery(为了方便起见,称之为查询)与 jQuery 之间唯一的区别是命名空间,在这个特定示例中为“YAHOO.foo.bar”与“$”。哦,还有两个 getElementsByTagName,否则你真的做得很好:) - 我们来做更多挑战,这很有趣。

  11. Pingback: jQuery 赢得事件选择器对决

  12. Pingback: jQuery 赢得事件选择器对决

  13. 嗯,我个人更喜欢 event:Selectors,我认为至少 - 它们俩都差不多。

    Dustin:关于 YUI…抱歉兄弟,但与 event:Selectors/jQuery 相比,那段代码太糟糕了(即使没有命名空间问题):)

    对于未来的版本,如果你能包含一个原始的 JS 版本...以方便与框架为我们带来的奇妙世界进行对比。

  14. Kyle,糟糕透顶?别忘了(就像我说的)Y! 的目标不是改变语言本身...而且它的代码仍然比 Prototype 少(对于这个特定的例子)。是因为我不得不手动写出 getElementsByTagName 吗?天哪,太苛刻了。

  15. Joel Birch 说:

    @Dustin,无论我如何重新检查你的代码片段,我都会得到一个多余的右花括号和分号(你代码片段的最后两个字符)。我是不是漏了什么?

  16. Joel Birch 说:

    感谢你澄清这一点 - 我以为我关于 javascript 的知识比实际还要差,因为我当时很困惑。
    我喜欢你的作品。

  17. Pingback: Dee’s-Planet! » 事件选择器对决:jQuery 挑战

  18. Pingback: 第 13 集:JavaScript 库概述

  19. Pingback: CODE POETRY » jQuery - 新兴 JavaScript

  20. Latte Boy 说:

    尝试使用 Prototype 1.5 示例,但一些错误导致它无法使用。以下是修改后的版本,它对我来说有效

    $$(‘#item li’,’#otheritem li’).each(function(li){
    Event.observe(li, ‘click’, function(event) {
    Event.element(event).setStyle({color: ‘#c00’});
    });
    });

    这两个修复
    1) 将不同的搜索字符串作为单独的参数添加到 $$ 中
    2) 使用 Event.element(event) 代替 Event.element(li)

  21. 我认为我更喜欢 eventSelectors。一方面,setStyle 散列表似乎更适合 CSS,因为它们都是键值对。由于没有使用 jQuery,我可能遗漏了一些东西,但设置值的 arguments 数组方法对我来说不太合适。

    无意冒犯,但 jQuery 中的事件连接对我来说就像纯粹的邪恶。;-) 设置器应该表明它们是设置器。在前面加上“set”并不必要,但像“click”这样的动词会立即让我联想到一些 DSL 驱动的功能测试框架。它不是在执行动作,所以它不应该表明是。抱歉,如果说得很苛刻...

    除此之外,它们都激起了我的兴趣,足以让我决定放弃 Behaviour。它已经为我服务了很久,但也许它的时代已经过去了。

    至于 YUI,是的,客户端 JavaScript 都是关于 DOM 操作的,因此 getElementsByTagName 的冗长性和过度的命名空间在这里真的对它不利。

  22. 看到针对 YUI 版本的评论,我感到非常惊讶,尽管这可能是因为受众是 pro-jQuery。jQuery 似乎很有趣,但很难争辩说它的代码对于不熟悉该库的人来说是不可读的。$$() 是什么?如果我管理一个项目,我需要在鼓励编写以下代码的库之间进行选择

    $(“#item li, #otheritem li”).click(function(){
    $(this).css(‘color’, ‘#c00’);
    });

    以及鼓励编写以下代码的库之间进行选择

    YAHOO.util.Event.on([YAHOO.util.Dom.get(‘item’).getElementsByTagName(‘li’),
    YAHOO.util.Dom.get(‘otheritem’).getElementsByTagName(‘li’)],
    ‘click’,function(){ YAHOO.util.Dom.setStyle(this,’color’,’#c00′); });

    如果我选择其他任何东西,我会在我的客户/公司身上造成巨大的维护成本。YUI 的冗长性是一个*特性*,它允许它保留在自己的命名空间中。如果你不喜欢它,只需一行代码就可以为任何你喜欢的元素创建别名。区别在于,别名仅在自定义代码(而不是库本身)中使用,并且由用户选择,而不是由库的作者选择。反对 getElementsByTagName 函数名称的长度,并不是反对 YUI。它是 DOM 的一部分 - 语言的一部分。如果你只是为了改变而改变方法的名称,那么你将迫使你的库用户学习你的 JavaScript 版本。这场对决中的不同解决方案,对我来说,仅仅证明了当今的库走向了多么错误的方向。4 种非标准、低可读性的方法来完成可以用标准 JavaScript 或 YUI 中的*实用工具*(而不是语言重写)帮助来完成的事情。

    JS 库应该帮助 JavaScript 开发人员。其他任何东西都是自负。

  23. $D = YAHOO.util.Dom;
    $E = YAHOO.util.Event;

    $E.on([$Dom.get(‘item’).getElementsByTagName(‘li’), $D.get(‘otheritem’).getElementsByTagName(‘li’)],’click’,function(){ $D.setStyle(this,’color’,’#c00′);
    });

  24. 我认为应该考虑不使用任何库的实现方法作为“控制”。

    var tags = {
    "item": document.getElementById("item").getElementsByTagName("li"),
    "otheritem": document.getElementById("otheritem").getElementsByTagName("li")
    }
    window.onload = function() {
    for (tag in tags) {
    tag.onclick = function() {
    this.style.color = "#c00";
    }
    }
    }

  25. Adrienne Travis 说:

    针对那个说 Yahoo 的代码更易于维护,因为更冗长的人 - 我最近才发现 jQuery。我是一名设计师和 HTML 黑客,我对 JavaScript 不太了解。我总是只是在网上寻找其他人为我的 JS 问题提供的不错的、非侵入性的解决方案 - 这就是我找到 jQuery 的方式。你知道吗?我之前见过其他 JS 框架(Behaviour、event:Selectors、Yahoo!) - 它们对我来说真的没有太大的意义。它们似乎和 JS 一直以来的那种半乱码一样。

    但 jQuery 呢?我*明白了*。我立刻就明白了 jQuery 的工作原理,以及如何使用它来做事情。在下载框架并浏览完教程后,我在*十分钟内*就为 jQuery 写了一个(非常简单,我承认)插件!

    因此,从一个主要从事艺术创作、Photoshop/HTML/CSS 黑客的角度来看,jQuery 真的很棒。

    而且在很多组织中,*我们*最终要负责更新 JavaScript,因为“真正的开发人员”忙于后端工作。因此,一个对*我们*有意义的库对我们来说是一个巨大的帮助!

    --Adrienne

  26. Adrienne,

    你的观点是你不知道 JavaScript,因此你发现 YUI 很困惑。你说你很容易理解 jQuery,因为它与典型的 JavaScript 不同。这正是我想说的。仅仅因为你不想学习 JavaScript,并不意味着你的 JavaScript 程序员也应该学习 jQuery。

  27. Sam Smoot 说:

    mwarden,

    我认为你对 jQuery 和 YUI 的比较过于肤浅。你说只需要一行代码就可以将 YUI 的过度命名空间和冗长代码简化。我则认为,我更愿意使用一个一开始就很简洁、文档完善的库,而不是使用另一个开发人员为了解决 YUI 冗长代码而设计的自己的解决方案。

    如果一个库使用起来如此痛苦,以至于你的开发人员最终不得不实现自己的无文档框架(或者只是一些别名集合)来封装它,那么它就不是可维护的。

  28. 我知道这是一篇旧文章,但我只是想指出,在 prototype 1.6.0 中,你可以执行以下操作

    $$(‘#item li, #otheritem li’).invoke(‘observe’, ‘click’, function() {
    $(this).setStyle({color: ‘#c00’});
    });