jQuery.click()vs onClick

Tec*_*hie 543 html javascript jquery jquery-events

我有一个巨大的jQuery应用程序,我正在使用以下两种方法进行点击事件.

第一种方法

HTML

<div id="myDiv">Some Content</div>
Run Code Online (Sandbox Code Playgroud)

jQuery的

$('#myDiv').click(function(){
    //Some code
});
Run Code Online (Sandbox Code Playgroud)

第二种方法

HTML

<div id="myDiv" onClick="divFunction()">Some Content</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript函数调用

function divFunction(){
    //Some code
}
Run Code Online (Sandbox Code Playgroud)

我在我的应用程序中使用第一种或第二种方法.哪一个更好?性能更好?和标准?

Sel*_*gam 544

使用$('#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);
Run Code Online (Sandbox Code Playgroud)

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

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

addEventListener是注册W3C DOM中指定的事件侦听器的方法.它的好处如下:

  • 它允许为事件添加多个处理程序.这对于即使使用其他库/扩展也需要正常工作的DHTML库或Mozilla扩展特别有用.
  • 当监听器被激活时(捕获与冒泡),它可以让您对阶段进行更细粒度的控制
  • 它适用于任何DOM元素,而不仅仅是HTML元素.

有关现代事件注册的更多信息 - > http://www.quirksmode.org/js/events_advanced.html

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

<button onclick="alert('Hello world!')">
Run Code Online (Sandbox Code Playgroud)

DOM元素属性,例如:

myEl.onclick = function(event){alert('Hello world');}; 
Run Code Online (Sandbox Code Playgroud)

很老,他们可以轻易写完.

应避免使用 HTML属性,因为它会使标记更大且可读性更低.对内容/结构和行为的担忧并没有很好地分离,使得更难找到bug.

与该问题DOM元素性质的方法是,只有一个事件处理程序可以绑定到每个事件的元件.

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

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

  • @zuallauz对于这种情况,jQuery提供`.delegate()`函数.它会将事件附加到将来在网站上出现的任何元素. (17认同)
  • @SimonRobb` .live`已弃用.对旧版本使用[`.delegate`](http://api.jquery.com/delegate/)或使用[`.on`](http://api.jquery.com/on/)获取更新的jQuery版本. (17认同)
  • 假设您运行`$('#myDiv').首先单击(function(){`代码,然后从JavaScript动态生成20行HTML,每行上都有一个按钮,单击时需要JavaScript执行相同的函数.如果你先这样做,那么它将无法工作,因为在生成HTML之前已经添加了事件处理程序.将`onclick ="functionName()"`放入到动态生成HTML然后按钮立即工作.或者你知道这种情况更优雅的解决方案吗? (13认同)
  • 我同意@supertonsky.我强烈反对$('#myDiv').click(function(){更好.在一个大的javascript应用程序中绑定一个事件变得非常难以找到绑定到该目标的所有引用.它是一个类绑定吗,一个id,一个孩子引用一个html标签?如果css发生变化,你需要更改的类名会发生什么呢?根据我与其他代码合作的经验,它变得非常难看. (5认同)
  • @Vega,好点.可读性怎么样?现在,您必须在页面上搜索所有引用的JS文件,以按元素的ID查看元素的所有单击处理程序,而不是搜索函数名称.你对此有何看法? (4认同)
  • @zuallauz jQuery` .live()`函数可能是一个更简单的解决方案,适用于[http://api.jquery.com/live/](http://api.jquery.com/live/).关于`.bind()`,`.live()`和`.delegate()`[here]之间差异的好文章(http://www.elijahmanor.com/2012/02/differences-between-jquery -bind-VS-live.html) (2认同)
  • @Jon您的不同意见是基于错误的编码实践.如果代码很难看,你应该考虑重构它......但是对于一个更好的方法没有意见,因为很难在丑陋的代码中找到引用.此外,如果您遵循简单的规则仅通过ID或类绑定处理程序,则很容易找到引用.任何其他方式,如使用遍历方法进行绑定都是错误的编码,如果代码不好,你就不能责怪标准. (2认同)
  • 是的,“应该避免使用HTML属性,因为它会使标记更大”,但是现在我必须为所有元素赋予id。另外,爱的回答是“应避免使用,因为它的*错误*” (2认同)
  • “应该避免 HTML 属性,因为它会使标记变大”记住这一点将导致意大利面条代码,HTML 属性事件 100% 有效。我不介意 ID 是否用于获取元素来绑定事件。但我见过很多“高级”开发人员仅使用类的长查询。结果?其他开发人员将很难搜索该事件的功能。我相信最好的做法是使用其他开发人员可以轻松找到该功能的任何东西,vue.js 上的人已经写过这个 https://vuejs.org/v2/guide/events.html#Why-Listeners-in-HTML (2认同)

Mar*_*lea 64

为了获得更好的性能,请使用本机JavaScript.为了加快开发速度,请使用jQuery.检查jQuery与Native Element Performance的性能比较.

我已经在Windows Server 2008 R2/7 64位上使用32位Firefox 16.0进行了测试

$('span'); // 6,604 operations per second
document.getElementsByTagName('span'); // 10,331,708 operations/sec
Run Code Online (Sandbox Code Playgroud)

对于单击事件,请检查本机浏览器事件与jquery触发器jQuery与本机单击事件绑定.

在Windows Server 2008 R2/7 64位上以32位格式在Chrome 22.0.1229.79中进行测试

$('#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
Run Code Online (Sandbox Code Playgroud)

  • jQuery应该能够在许多不同的环境中运行,这使得它更容易编写,维护,但如果速度是最重要的,那么jQuery不是答案 (9认同)

Mic*_*zyn 39

据我所知,你的问题不是关于是否使用jQuery.更确切地说:将事件内联在HTML中还是通过事件监听器更好?

不推荐使用内联绑定.此外,您只能将一个函数绑定到某个事件.

因此,我建议使用事件监听器.这样,您就可以将许多函数绑定到单个事件,并在以后根据需要取消绑定它们.考虑这个纯JavaScript代码:

querySelector('#myDiv').addEventListener('click', function () {
    // Some code...
});
Run Code Online (Sandbox Code Playgroud)

这适用于大多数现代浏览器.

但是,如果您已在项目中包含jQuery - 只需使用jQuery:.on.click函数.

  • 这样你仍然只能注册一个"表达式".例如,如果`handler1`抛出错误,`handler2`和`handler3`就不会被调用.此外,您无法动态添加和删除侦听器中的某些功能.最后但并非最不重要的是,`handler1`,`handler2`和`handler3`必须在全局范围内声明,这是一种气味. (2认同)

Caf*_*eek 15

你可以将它们组合起来,使用jQuery将函数绑定到click

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

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

function divFunction(){
 //some code
}
Run Code Online (Sandbox Code Playgroud)


gee*_*man 14

$('#myDiv').click更好,因为它将JavaScript代码与HTML分开.必须尝试保持页面行为和结构不同.这有很大帮助.

  • 这个答案是有道理的,因为设计和编写js的人在大多数情况下是不同的.自发布以来差不多4年后,对此进行投票感到奇怪! (2认同)

Rah*_*hul 14

为此,它将为您提供标准和性能.

 $('#myDiv').click(function(){
      //Some code
 });
Run Code Online (Sandbox Code Playgroud)

因为第二种方法是简单的JavaScript代码,并且比jQuery更快.但这里的表现大致相同.


小智 11

恕我直言,onclick是仅在满足以下条件时优先于.click的方法:

  • 页面上有很多元素
  • 只有一个事件要为click事件注册
  • 你担心移动性能/电池寿命

我之所以形成这种观点,是因为移动设备上的JavaScript引擎比同代产品中的JavaScript引擎慢4到7倍.当我访问我的移动设备上的网站并接收抖动滚动时,我讨厌它,因为jQuery以牺牲我的用户体验和电池寿命为代价来绑定所有事件.另一个最近的支持因素,虽然这应该只是政府机构关注的问题;),我们有一个IE7弹出窗口,上面有一个消息框,说明JavaScript进程需要很长时间......等待或取消进程.每当有很多元素通过jQuery绑定时就会发生这种情况.


Ant*_*iev 10

作品的差异.如果使用click(),则可以添加多个函数,但如果使用属性,则只执行一个函数 - 最后一个.

DEMO

HTML

<span id="JQueryClick">Click #JQuery</span> </br>
<span id="JQueryAttrClick">Click #Attr</span> </br>
Run Code Online (Sandbox Code Playgroud)

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')" )
Run Code Online (Sandbox Code Playgroud)

如果我们谈论性能,在任何情况下直接使用总是更快,但使用属性,您将只能分配一个功能.


Chr*_*ris 8

关注点的分离在这里是关键,因此事件绑定是普遍接受的方法.这基本上是许多现有答案所说的.

但是,不要过快地抛弃声明性标记的想法.它有它的位置,并且像Angularjs这样的框架是其核心.

需要有一个理解,<div id="myDiv" onClick="divFunction()">Some Content</div>因为它被一些开发人员滥用,整个人都被羞辱了.所以它达到了亵渎神圣的程度,很像tables.一些开发人员实际上避免tables使用表格数据.这是人们在不理解的情况下表现的完美典范.

虽然我喜欢把我的行为与我的观点分开的想法.我发现标记没有问题,声明它做了什么(不是它如何做,这是行为).它可能是实际的onClick属性或自定义属性的形式,就像bootstraps 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>
Run Code Online (Sandbox Code Playgroud)

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

注意第二个例子的主要缺点是全局命名空间的污染.这可以通过使用上面的第三个替代方案,或者像Angular这样的框架及其具有自动范围的ng-click属性来规避.


Mar*_*.io 5

<whatever onclick="doStuff();" onmouseover="in()" onmouseout="out()" />
Run Code Online (Sandbox Code Playgroud)

onclick、onmouseover、onmouseout 等事件实际上对性能不利(主要是在Internet Explorer 中,去图)。如果您使用Visual Studio 进行编码,当您使用这些运行页面时,其中的每一个都会创建一个单独的 SCRIPT 块,占用内存,从而降低性能。

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

为这些事件中的任何一个创建 evenHandlers 总是更好,一个事件可以捕获成百上千个项目,而不是为每个项目创建数千个单独的脚本块!

(另外,其他人都在说。)


Kam*_*ski 5

表现

这里已经有很多很好的答案,然而,作者有时会提到性能,但实际上还没有人调查它 - 所以我将在这里重点关注这个方面。今天,我在 Chrome 83.0、Safari 13.1 和 Firefox 77.0 上进行测试,以获得有问题的解决方案以及一些替代解决方案(其中一些在其他答案中提到过)。

结果

我在这里比较解决方案啊,因为它们对元素进行操作id。我还展示了使用class(I,J,K) 作为参考的解决方案的结果。

  • 基于 html 内联处理程序绑定 (B) 的解决方案对于 Chrome 来说速度最快,对于少量元素来说速度最快
  • 基于getElementById(C,D) 的解决方案速度很快,对于大量元素,在 Safari 和 Firefox 上速度最快
  • 基于 I、J 的参考解决方案对于大量元素而言速度最快,因此在这种情况下值得考虑使用class替代id方法
  • 基于 jQuery.click (A) 的解决方案是最慢的

在此输入图像描述

细节

其实要设计这个问题的性能测试并不容易。我注意到,对于所有经过测试的解决方案,10K div-s 的触发事件的性能都很快,并且手动我无法检测到它们之间的任何差异(您可以运行下面的代码片段来自行检查)。因此,我重点关注两种情况下生成 html 和绑定事件处理程序的测量执行时间

// https://stackoverflow.com/questions/12627443/jquery-click-vs-onclick
let a= [...Array(10000)];

function clean() { test.innerHTML = ''; console.clear() }

function divFunction(el) {
  console.log(`clicked on: ${el.id}`);
}

function initA() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> $(`#myDiv${i}`).click(e=> divFunction(e.target)));
}

function initB() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box" onclick="divFunction(this)">${i}</div>`).join``;
}

function initC() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.getElementById(`myDiv${i}`).onclick = e=> divFunction(e.target) );
}

function initD() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.getElementById(`myDiv${i}`).addEventListener('click', e=> divFunction(e.target) ));
}

function initE() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.querySelector(`#myDiv${i}`).onclick = e=> divFunction(e.target) );
}

function initF() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.querySelector(`#myDiv${i}`).addEventListener('click', e=> divFunction(e.target) ));
}

function initG() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> window[`myDiv${i}`].onclick = e=> divFunction(e.target) );
}

function initH() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> window[`myDiv${i}`].addEventListener('click',e=> divFunction(e.target)));
}

function initI() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  [...document.querySelectorAll(`.box`)].map(el => el.onclick = e=> divFunction(e.target));
}

function initJ() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  [...document.querySelectorAll(`.box`)].map(el => el.addEventListener('click', e=> divFunction(e.target)));
}

function initK() {  
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  $(`.box`).click(e=> divFunction(e.target));
}



function measure(f) {  
  console.time("measure "+f.name);
  f();
  console.timeEnd("measure "+f.name)
}
Run Code Online (Sandbox Code Playgroud)
#test {
  display: flex;
  flex-wrap: wrap;
}

.box {
  margin: 1px;
  height: 10px;
  background: red;
  font-size: 10px;
  cursor: pointer;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>This snippet only presents used solutions. Click to solution button and then click on any red box to trigger its handler</div>
<button onclick="measure(initA)">A</button>
<button onclick="measure(initB)">B</button>
<button onclick="measure(initC)">C</button>
<button onclick="measure(initD)">D</button>
<button onclick="measure(initE)">E</button>
<button onclick="measure(initF)">F</button>
<button onclick="measure(initG)">G</button>
<button onclick="measure(initH)">H</button>
<button onclick="measure(initI)">I</button>
<button onclick="measure(initJ)">J</button>
<button onclick="measure(initK)">K</button>
<button onclick="clean()">Clean</button>

<div id="test"></div>
Run Code Online (Sandbox Code Playgroud)

这是 Chrome 的示例测试

在此输入图像描述