addEventListener 与 onclick

2023-11-26

有什么区别addEventListener and onclick?

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

上面的代码一起驻留在一个单独的.js文件,并且它们都工作得很好。


两者都是正确的,但它们本身都不是“最好的”,开发人员选择使用这两种方法可能是有原因的。

事件监听器(addEventListener和 IE 的attachEvent)

早期版本的 Internet Explorer 实现 JavaScript 的方式与几乎所有其他浏览器不同。对于版本低于 9 的版本,您可以使用attachEvent[doc] 方法,像这样:

element.attachEvent('onclick', function() { /* do stuff here*/ });

在大多数其他浏览器(包括 IE 9 及更高版本)中,您使用addEventListener[doc], 像这样:

element.addEventListener('click', function() { /* do stuff here*/ }, false);

使用这种方法(DOM 2 级事件),理论上您可以将无限数量的事件附加到任何单个元素。唯一的实际限制是客户端内存和其他性能问题,这对于每个浏览器来说都是不同的。

上面的例子代表使用匿名函数[doc]。您还可以使用函数引用添加事件侦听器[doc] 或闭包[doc]:

const myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

的另一个重要特点addEventListener是最后一个参数,它控制监听器如何对冒泡事件做出反应[doc]。我在示例中传递了 false,这对于 95% 的用例来说是标准的。没有同等的论据attachEvent,或者使用内联事件时。

内联事件(HTMLonclick=""财产和element.onclick)

在所有支持 JavaScript 的浏览器中,您可以内联事件侦听器,即直接在 HTML 代码中。您可能已经看过这个:

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

大多数有经验的开发人员都会避开这种方法,但它确实可以完成工作;它简单而直接。您不能在这里使用闭包或匿名函数(尽管处理程序本身是某种匿名函数),并且您对范围的控制是有限的。

你提到的另一种方法:

element.onclick = function () { /*do stuff here */ };

... 相当于内联 JavaScript,只不过您可以更好地控制范围(因为您编写的是脚本而不是 HTML)并且可以使用匿名函数、函数引用和/或闭包。

内联事件的显着缺点是,与上述事件侦听器不同,您可能只分配了一个内联事件。内联事件存储为元素的属性/属性[doc],意味着它可以被覆盖。

使用示例<a>从上面的 HTML 中:

const element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };

...当您单击该元素时,您会only请参阅“Did stuff #2” - 您覆盖了第一个分配的onclick属性具有第二个值,并且您覆盖了原始的内联 HTMLonclick财产到.在这里查看:http://jsfiddle.net/jpgah/.

从广义上讲,不要使用内联事件。它可能有特定的用例,但如果您不能 100% 确定您有该用例,那么您不会也不应该使用内联事件。


现代 JavaScript(Angular 等)

自从这个答案最初发布以来,像 Angular 这样的 JavaScript 框架已经变得更加流行。您将在 Angular 模板中看到如下代码:

<button (click)="doSomething()">Do Something</button>

这看起来像一个内联事件,但事实并非如此。这种类型的模板将被转换为更复杂的代码,在幕后使用事件侦听器。我在这里写的有关事件的所有内容仍然适用,但您至少脱离了一层本质。您应该了解具体细节,但如果您的现代 JavaScript 框架最佳实践涉及在模板中编写此类代码,请不要觉得您正在使用内联事件 – 事实并非如此。


哪个最好?

问题是浏览器兼容性和必要性的问题。您是否需要将多个事件附加到一个元素?未来你会吗?很有可能,你会的。 AttachEvent 和 addEventListener 是必需的。如果没有,内联事件可能看起来可以解决问题,但你最好为未来做好准备,虽然这看起来不太可能,但至少是可以预测的。您有可能必须转向基于 JavaScript 的事件侦听器,因此您不妨从那里开始。不要使用内联事件。

jQuery 和其他 JavaScript 框架将 DOM 2 级事件的不同浏览器实现封装在通用模型中,因此您可以编写跨浏览器兼容的代码,而不必担心 IE 的历史。与 jQuery 相同的代码,所有跨浏览器并准备好摇滚:

$(element).on('click', function () { /* do stuff */ });

不过,不要仅仅为了这一件事就跑去获取一个框架。您可以轻松地推出自己的小实用程序来处理旧浏览器:

function addEvent(element, evnt, funct){
  if (element.attachEvent)
   return element.attachEvent('on'+evnt, funct);
  else
   return element.addEventListener(evnt, funct, false);
}

// example
addEvent(
    document.getElementById('myElement'),
    'click',
    function () { alert('hi!'); }
);

Try it: http://jsfiddle.net/bmArj/

考虑到所有这些,除非您正在查看的脚本以其他方式考虑了浏览器差异(在您的问题中未显示的代码中),否则使用的部分addEventListener在低于 9 的 IE 版本中无法工作。

文档和相关阅读

  • W3 HTML 规范,元素事件处理程序属性
  • MDN 上的 element.addEventListener
  • MSDN 上的 element.attachEvent
  • jquery.com
  • quirksmode博客“活动简介”
  • Google 的 CDN 托管 JavaScript 库
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

addEventListener 与 onclick 的相关文章

  • 为什么 `obj.foo = function() { };` 没有将名称 `foo` 分配给函数?

    从 ES2015 ES6 开始 函数有了专有名称 包括官方名称 name属性 而函数创建时的赋值除了明显的函数声明和命名函数表达式之外还有多种方式 比如给变量赋值 函数的名字设置为变量的名字 给对象属性赋值 函数的名称设置为属性的名称 甚至
  • 在 Meteor.method 中调用函数返回未定义

    过去几天我一直在尝试从 Meteor 方法获取返回对象 每次我这样做我都会得到undefined在客户端上 Meteor methods CORSTest function let url www theverge com 2017 4 1
  • 根据嵌套值使用数组过滤对象数组

    我正在尝试根据某些嵌套对象过滤数组 我准备了一些Fiddle http jsfiddle net NZnN2 249 输入数组如下所示 let arrayOfElements name a subElements surname 1 sur
  • 将鼠标悬停在图像上以显示按钮,并且将鼠标悬停在实际按钮上时不会触发

    我试图让按钮在悬停在图像上时出现 以下作品 jQuery show image mouseenter function jQuery the buttons animate opacity 1 1500 mouseout function
  • 如何从ArrayBuffer中获取二进制字符串?

    JavaScript中如何从ArrayBuffer中获取二进制字符串 我不想对字节进行编码 只需将二进制表示形式获取为字符串 提前致谢 以下代码将一致地转换ArrayBuffer to a String并再次返回 而不会丢失或添加任何额外的
  • 茉莉花节点没有输出

    我是 JavaScript Node js 和 jasmine 的新手 我正在尝试运行 Node Craftsman Book 一书中的测试 FilesizeWatcher 我创建了 package json 文件并运行 npm insta
  • 如何在CKEditor 5中监听焦点事件

    我想听一下 CKEditor 5 中的焦点事件 我认为这样的事情会起作用 但回调从未被调用 document querySelector editable ClassicEditor create el then editor gt edi
  • 如何在 Chrome 中实现抓取光标图标?

    我知道可以在 Chrome 中使用抓取光标图标 当然是在 Gmail 中 但我不知道如何在我的代码中实现它 我已经尝试过 在CSS中 body cursor grab body cursor webkit grab body cursor
  • 代码点火器 JSON

    你好 我使用 codeigniter 然后我从控制器中的数据库中回显输出 然后在我的视图文件中执行以下操作 但它没有显示任何内容 S 我的模型文件 function forumList this gt db gt select oversk
  • WebDriver:更改事件未触发

    我有一个使用 KnockoutJS 的应用程序 我正在尝试编写一些测试表单的测试 如果您不了解 KnockoutJS 简单来说 它提供了从我的视图到我的数据模型的绑定 这意味着当我在输入字段中键入值时 我的基础对象会自动使用该输入字段值进行
  • 为什么我的 onclick 事件自动触发

    加载页面时最初显示 Hello World 我希望它仅在单击按钮后显示 我知道我可以通过向按钮添加内联事件侦听器来做到这一点 我可以只用脚本编写所有这些代码吗
  • JointJS - 处理链接删除点击

    创建链接后 将鼠标悬停在其上会显示红色 X 以将其删除 单击此按钮将触发一系列事件 通过订阅 全部 活动收集 单元格 向下指针 链接 向下指针 cell pointermove x5 似乎可疑 单元格 指针向上 在浏览了文档并花费了太长时间
  • 有没有办法在 TypeScript 2+ 中全局添加类型定义?

    我有一堆简单的 ts files 不是项目 即独立的 ts 脚本 他们使用一些 Node js 功能 TypeScript 和节点类型定义通过安装 npm install g typescript npm install g types n
  • django ajax post 403被禁止

    使用 django 1 4 当我尝试从我的 javascript 做我的 django 服务器上的帖子时 我收到 403 错误 我的 get 工作正常 尽管问题仅出在帖子上 也尝试过 csrf exempt但没有运气 更新 我现在可以发布我
  • while 循环元素状态 cypress

    我有一个问题 我想单击一个按钮直到它消失 但次数可能会有所不同 所以我想检查可见性状态 当可见 true时单击按钮 当可见 false时结束测试 但问题是我不知道如何循环从获取元素到末尾的所有链 单击按钮一次 由于中断而停止 如果我删除中断
  • 单击react.js 切换列表的背景颜色

    我正在尝试创建一个具有以下功能的列表 悬停时更改列表项的背景颜色 单击时更改列表项的背景颜色 在单击的元素之间切换背景颜色 即列表中只有一个元素可以具有 clicked 属性 我已经执行了 onhover 1 和 2 功能 但无法实现第三个
  • Tween JS 基础知识之三个 JS 立方体

    我是 Tween JS 的新手 尝试使用 Tween 制作一个向右移动的简单动画 下面是我在 init 函数中的代码 我使用的是三个 JS var geometry new THREE CylinderGeometry 200 200 20
  • 在 中动态添加链接样式表 [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 如何将链接
  • 盒式捆绑包与 MVC4 捆绑包

    我目前正在开发一个原型 ASP NET MVC 3 解决方案 该解决方案将用作多个项目重写的基础 来自 Web 表单 我的目标之一是跨应用程序实现一些脚本管理 而不是我们目前没有的目标 MVC 3有一个缺陷恕我直言 如果您需要在部分视图或模
  • 响应式菜单:悬停子菜单显示错误

    简而言之 我根据教程创建了一个响应式菜单 当您将鼠标悬停在投资组合按钮上时 菜单应该显示子菜单 而在移动模式下 您需要按该按钮才能显示子菜单 效果很好 问题是该教程有一个错误 如果您在桌面模式下按组合按钮 子菜单将不会再次显示 除非您按 单

随机推荐