jQuery.click()与onClick的区别

619

我有一个非常庞大的jQuery应用程序,我在使用以下两种方法处理点击事件。

第一种方法

HTML

<div id="myDiv">Some Content</div>

jQuery

$('#myDiv').click(function(){
    //Some code
});

第二种方法

HTML

<div id="myDiv" onClick="divFunction()">Some Content</div>

JavaScript函数调用

function divFunction(){
    //Some code
}

在我的应用程序中,我使用第一种或第二种方法。哪一种更好?对性能来说更好吗?还有标准方面的考虑吗?


9
您可以在此了解不同的事件处理方式及其优缺点:http://www.quirksmode.org/js/introevents.html。jQuery只是高级事件注册的一种好的封装。 - Felix Kling
14
记得将 click 函数放在 $(document).ready(function() 中。 - joan16v
18个回答

617

使用 $('#myDiv').click(function(){ 更好,因为它遵循标准的事件注册模型。(jQuery 在内部使用 addEventListenerattachEvent)。

基本上,在现代方式中注册事件是处理事件的不显眼的方式。此外,要为同一目标注册多个事件侦听器,可以对该目标调用addEventListener()

var myEl = document.getElementById('myelement');

myEl.addEventListener('click', function() {
    alert('Hello world');
}, false);

myEl.addEventListener('click', function() {
    alert('Hello world again!!!');
}, false);

http://jsfiddle.net/aj55x/1/

为什么要使用addEventListener? (来自MDN)

addEventListener是注册事件监听器的W3C DOM规范方式。其好处如下:

  • 它允许为一个事件添加多个处理程序。这对于需要良好运行甚至在使用其他库/扩展时的DHTML库或Mozilla扩展特别有用。
  • 它提供了更精细的控制,确定何时激活侦听器(捕获或冒泡阶段)。
  • 它适用于任何DOM元素,而不仅仅是HTML元素。

更多关于现代事件注册的内容 -> http://www.quirksmode.org/js/events_advanced.html

还有其他方法,例如设置HTML属性HTML属性,示例:

<button onclick="alert('Hello world!')">

或者DOM元素属性,例如:

myEl.onclick = function(event){alert('Hello world');}; 

老的HTML属性很容易被覆盖,应该避免使用它们,因为它们会使标记变得更大且不易读取。 内容/结构和行为的关注点未分离,使得查找错误更加困难。

使用DOM元素属性方法的问题是每个事件只能绑定一个事件处理程序到元素上。

有关传统事件处理的更多信息-> http://www.quirksmode.org/js/events_tradmod.html

MDN 参考文献: https://developer.mozilla.org/en-US/docs/DOM/event


14
假设您先运行了$('#myDiv').click(function(){代码,然后从JavaScript动态生成20行HTML,每行都有一个按钮,当点击按钮时,需要执行同样的JavaScript函数。如果您首先执行这个步骤,那么它将不起作用,因为事件处理程序已在生成HTML之前添加。似乎更容易的方法是在动态生成的HTML中添加onclick="functionName()",这样按钮就可以立即工作了。或者,您是否知道这种情况的更优雅的解决方案? - zuallauz
18
对于这种情况,jQuery 提供了 .delegate() 函数。它将事件附加到在网站未来出现的任何元素上。 - Zefiryn
18
@SimonRobb .live已被弃用。对于旧版本,请使用.delegate,对于新的 jQuery 版本,请使用.on - Selvakumar Arumugam
6
@Vega,说得好。那阅读性如何?现在你必须搜索页面上所有引用的JS文件,通过元素ID查找所有点击处理程序,而不是搜索函数名称。你对此有什么看法? - supertonsky
8
我同意@supertonsky的观点。我强烈反对认为$('#myDiv').click(function(){更好。在一个大型的Javascript应用程序中,与事件绑定变得非常难以找到所有绑定到该目标的引用。它是绑定类、ID、子引用到HTML标记吗?如果CSS更改并且您绑定到的类名需要更改会发生什么?根据我的经验,在处理其他人的代码时,它变得非常丑陋而快速。 - Jon
显示剩余12条评论

68
为了获得更好的性能,请使用本机JavaScript。为了更快的开发,请使用jQuery。在jQuery vs Native Element Performance上查看性能比较。
我在Windows Server 2008 R2/7 64位上的Firefox 16.0 32位进行了测试。
$('span'); // 6,604 operations per second
document.getElementsByTagName('span'); // 10,331,708 operations/sec

对于点击事件,请参考原生浏览器事件 vs jQuery 触发或者jQuery vs 原生点击事件绑定

在 Windows Server 2008 R2 / 7 64 位操作系统上,使用 Chrome 22.0.1229.79 32 位进行测试。

$('#jquery a').click(window.testClickListener); // 2,957 operations/second

[].forEach.call( document.querySelectorAll('#native a'), function(el) {
    el.addEventListener('click', window.testClickListener, false);
}); // 18,196 operations/second

9
jQuery应该能够在许多不同的环境中运行,这使其更加健壮,并且更容易编写和维护。但是,如果速度最重要,则jQuery并非最佳选择。 - Paul C
使用forEach时要小心,因为它并不是所有浏览器都兼容的,例如IE可能不支持。也许一个polyfill会很有用。 - khaled_webdev

43

根据我的理解,你的问题并不是关于是否使用jQuery。相反,问题应该是:在HTML中绑定事件或通过事件监听器绑定事件哪种更好?

内联绑定已经过时。此外,这种方式只能将一个函数绑定到特定事件上。

因此,我建议使用事件监听器。这样,你可以将许多函数绑定到一个事件上,并在需要时取消绑定。考虑以下纯JavaScript代码:

querySelector('#myDiv').addEventListener('click', function () {
    // Some code...
});

这在大多数现代浏览器中都可以工作。

但是,如果您的项目中已经包含了jQuery,那么只需使用jQuery:.on.click函数。


可以使用内联HTML注册多个函数,例如<div onclick="handler1();handler2();handler3();"></div>。 - Kira
2
这样,您仍然只注册了一个“表达式”。例如,如果handler1抛出错误,则永远不会调用handler2handler3。此外,您无法动态添加和删除侦听器中的某些函数。最后但并非最不重要的是,handler1handler2handler3必须在全局范围内声明,这是一种不好的做法。 - Michał Miszczyszyn
我提到过我不确定禁用JavaScript。我没有误导或欺骗他人。 - Kira
在这种情况下,您可以尝试以下代码:<div onclick="function() { try { handler1();handler2();handler3(); } catch { } }"></div> - Kira
指出帖子中的问题:“内联绑定已被弃用。”你确定吗?(HTML规范§8.1.7.1不同意https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-content-attributes)我的印象是:每个人都在互相回应,说使用它们是一种不好的做法,但很少有人批判性地思考他们摄入的模因。一些抗体:事件侦听器是命令式(而不是声明式)链接的(通常通过某些查找,经常通过添加不必要的属性来帮助),在DOM上是不可见的,并且无法通过编辑活动HTML文档上的属性进行重连。 - wtr
显示剩余2条评论

23

选择这个选项,因为它既提供标准又提高了性能。

 $('#myDiv').click(function(){
      //Some code
 });

因为第二种方法是简单的JavaScript代码而且比jQuery更快。但是性能会大致相同。


21
你可以将它们合并,使用jQuery将函数绑定到点击事件上。
<div id="myDiv">Some Content</div>

$('#myDiv').click(divFunction);

function divFunction(){
 //some code
}

16

$('#myDiv').click 更好,因为它将 JavaScript 代码与 HTML 分离开来。应该尝试保持页面的行为和结构不同。这会很有帮助。


2
这个答案是有道理的,因为设计和编写JS代码的人在大多数情况下是不同的。而且在发布了将近4年之后点赞感觉有些奇怪! - LearningEveryday

13

工作原理不同。如果您使用click(),则可以添加多个函数,但如果您使用属性,则只会执行最后一个函数。

演示

HTML

<span id="JQueryClick">Click #JQuery</span> </br>
<span id="JQueryAttrClick">Click #Attr</span> </br>

JavaScript

$('#JQueryClick').click(function(){alert('1')})
$('#JQueryClick').click(function(){alert('2')})

$('#JQueryAttrClick').attr('onClick'," alert('1')" ) //This doesn't work
$('#JQueryAttrClick').attr('onClick'," alert('2')" )

如果我们谈论性能,直接使用总是更快的,但是使用属性,您只能分配一个函数。


我们可以使用属性像 $('#JQueryAttrClick').attr('onClick'," alert('2');alert('3');alert('4')") 来执行多个函数。 - Kira

11

在我的观点中,当满足以下条件时,onclick是优于.click的首选方法:

  • 页面上有许多元素
  • 仅需注册一个单击事件
  • 您担心移动设备性能/电池寿命

我形成这个观点是因为移动设备上的JavaScript引擎比同一代桌面引擎慢4至7倍。我讨厌当我用移动设备访问网站时,因为jQuery绑定了所有事件而导致卡顿滚动,从而损害了我的用户体验和电池寿命。最近的另一个支持因素(尽管只应该关心政府机构;)),我们遇到IE7弹出一个消息框,指出JavaScript进程花费太长时间......等待或取消进程。每当有许多元素通过jQuery绑定时,这种情况都会发生。


10

注意分离关注点非常重要,因此事件绑定是通常被接受的方法。这基本上就是很多现有答案所说的。

然而不要太快地放弃声明性标记的想法。它有它的位置,在像Angularjs这样的框架中,是核心。

需要了解整个<div id="myDiv" onClick="divFunction()">Some Content</div>如此受到负面评价,是因为它被一些开发人员滥用。因此,它达到了亵渎神圣的程度,就像表格一样。一些开发人员实际上避免使用表格进行表格数据。这是人们在没有理解的情况下行事的完美例证。

尽管我喜欢将我的行为与视图分开的想法。但我认为把做什么(而不是如何做)的标记声明出来没有问题。它可以采用实际的onClick属性形式或自定义属性形式,就像bootstrap的javascript组件一样。

这样,通过一眼看到标记,您就可以看到它正在做什么,而不是试图查找JavaScript事件绑定器。

因此,作为上述第三个选择,使用数据属性来在标记中声明行为。行为被保留在视图之外,但您可以一眼看到正在发生的事情。

Bootstrap示例:

<button type="button" class="btn btn-lg btn-danger" data-toggle="popover" title="Popover title" data-content="And here's some amazing content. It's very engaging. Right?">Click to toggle popover</button>

来源:http://getbootstrap.com/javascript/#popovers

注意:第二个示例的主要缺点是全局命名空间的污染。这可以通过使用上述的第三种替代方法或像Angular这样的框架及其自动作用域的ng-click属性来规避。


+1!:D 声明式形式的其他好处:由于事件处理程序属性在DOM节点上的可见性(无法使用addEventListener),因此可以(如我所做的那样)创建一个属性编辑器,编辑给定元素的属性值,在实时HTML文档上强大地重构元素的功能。 - wtr

5
<whatever onclick="doStuff();" onmouseover="in()" onmouseout="out()" />

onclick、onmouseover、onmouseout等事件实际上对性能来说是不利的(主要是在Internet Explorer中,你懂的)。如果你使用Visual Studio编写代码,并且在页面中使用这些事件,每一个事件都会创建一个单独的SCRIPT块占用内存,从而降低性能。

更不用说你应该有关注点分离:JavaScript和布局应该分离!

最好为任何这些事件创建事件处理程序,一个事件可以捕获数百/数千个项目,而不是为每个项目创建成千上万个单独的脚本块!

(还有,其他人所说的一切。)


Angular、Vue等框架打破了分离的概念,但在使用这些框架编写应用程序时并不会引起任何问题(事实上,它加速了软件创建的过程)。 - Kamil Kiełczewski
1
@KamilKiełczewski 自2012年以来,很多东西都发生了变化!在过去,这曾经是一个主要的SOC问题,但现在我们在任何地方都可以做到。我想唯一的区别就是我们让某些框架编译我们的代码并将(点击)或其他事件转换成不同的东西。但最终的思路是相同的,对吧:D 真是令人震惊,事物会如此地回到起点! - Mark Pieszak - Trilon.io
我同意你的观点,并已经在这里写下了我的想法:(https://dev59.com/-2025IYBdhLWcg3wqn0N#54769527) - Kamil Kiełczewski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接