HTML 事件属性和使用 HTML DOM 分配事件有什么区别?

What is the difference between HTML Event Attributes and Assign Events Using the HTML DOM?

HTML 事件属性:

<button onclick="displayDate()">Try it</button>

使用 HTML DOM 分配事件:

<script>

document.getElementById("myBtn").onclick = function(){ displayDate() };

</script>

这两个有什么区别?使用 (Assign Events Using the HTML DOM) 有什么好处?

谢谢

没有区别。 OnClick 是同一个事件。

如果您想调用不同的方法,使用 javascript 您可以操纵在 OnClick 出现时要执行的操作。

好处是你不会把js代码和html混在一起,它允许你分离编程层。这使您的代码更清晰,更不容易出现错误。 符合网页可访问性规则和良好编程基础的做法。

HTML5 规范的条款 6.1.5 Events 中描述了差异(或者更确切地说,连接)。基本区别在于,像 onclick 这样的事件属性包含这样执行的 JavaScript 代码(通常是函数调用),而元素节点的 click 属性是对函数定义的引用。如果您在 HTML 源代码中使用 onclick="displayDate()",然后在浏览器的开发人员工具中检查 DOM,您会发现原则上连接更复杂。

实际差异很大,取决于意见和编码风格。使用 onclick 属性可以让任何阅读 HTML 源代码的人立即明白事件处理程序的存在。当主要将 HTML 代码作为结构化数据阅读时,这也可能是一个缺点。但是,当多个元素需要具有相同的事件处理程序时(例如,当你想点击 any link 时触发一些处理程序(在 link 操作之前或代替正常的操作)。使用 JavaScript,您可以有一个循环,将相同的函数分配给所有 link,这与在 HTML 标记中复制相同的 onclick 属性相反。

差别很大

通过 HTML 事件属性设置的事件处理程序是我们处理事件的第一种方式 - 在 DOM 出现之前。这种设置事件的方式被称为 DOM 级别 0(就像在没有标准之前的事实标准)。当这是这样做的时候(大约 1995 年),它很好,因为我们别无选择。但是,将属性值转换为事件处理代码的方式是这样处理的:

HTML 元素声明了一个事件属性,该属性的值是事件发生时应执行的 JavaScript 代码:

<input type="button" onclick="alert('You clicked me!')" value="Click me">

请注意 onclick 的值不是函数引用,只是将代码松散到 运行.

这实际上是由浏览器通过在全局范围内创建一个函数来实现的,该函数充当所提供代码的包装器。我们可以在这里看到:

// Output the value of the onclick property.
// Note the value supplied in the HTML
// is wrapped in a function that we didn't create
alert(document.querySelector("input").onclick);
<input type="button" onclick="alert('You clicked me!')" value="Click me">

由于在全局包装函数中自动包装了属性值,非直观的事情经常发生如下:

function foo(){
  // This function is invoked by clicking the HTML input element
  // so, we may reasonably expect that "this" would reference that
  // element. But, as you'll see, it doesn't.
  alert("You clicked the " + this.nodeName + " element.");
}
<input type="button" onclick="foo()" value="Click me">

以上报告 undefined 因为实际上,this 在该上下文中指的是全局 window 对象,它没有 nodeName 属性。但是,如果您不知道全局包装器(以及您为什么会知道),这将非常令人困惑,因为 DOM 事件处理程序使用的 this 几乎总是引用 DOM 元素导致事件触发。

当 DOM 级别 1 事件处理规范问世(1998 年)时,一种配置事件的新方法也应运而生。我们现在有代表 HTML 元素的对象,每个对象都有映射到元素属性的属性。出于这个原因,许多人(直到今天)仍然相信使用属性或对象属性在很大程度上是一回事。但是,存在重要差异( 在我的另一个答案中:参见答案的后半部分),因为属性用于设置值,这会影响状态,而属性用于覆盖属性和设置状态。

因此,对于 DOM 事件处理,我们将执行以下操作,您将看到,设置事件回调,不是作为要执行的松散代码,而是通过存储对函数的引用事件发生时被调用。因为我们提供了函数,所以它具有我们存储它的 DOM 对象的范围,我们不再需要用 Global 包装松散的命令。这会导致 this 绑定按预期工作:

// Just a reference to a function is used with event 
// properties. Not "loose" code. And, because the function
// is actually being stored with the DOM element, this binding
// works as expected.
document.querySelector("input").onclick = foo;

function foo(){
  // This function is invoked by clicking the HTML input element
  // so, we may reasonably expect that "this" would reference that
  // element. But, as you'll see, it doesn't.
  alert("You clicked the " + this.nodeName + " element.");
}
<input type="button" value="Click me">

DOM 事件处理的额外好处是我们将 JavaScript 与 HTML 分开(即关注点分离)。这是一个好处,但不是改变的驱动力。

现在,已经解释了这两种注册事件机制之间的差异,故事还没有完成。 DOM 事件属性仍然存在一个问题,如果你想设置多个事件处理程序,你没有一种干净的方法来做到这一点,因为你只能在给定的 [=96 中存储一个函数引用=].因此,对于现代事件处理,我们使用 .addEventListener(),它允许我们为我们想要的事件注册尽可能多的事件回调,并且我们获得额外的好处,因为我们知道我们注册的回调将按照以下顺序调用我们注册了他们。

// Register an event listener:
document.querySelector("input").addEventListener("click", foo1);

// Register more event listeners:
document.querySelector("input").addEventListener("click", foo3);
document.querySelector("input").addEventListener("click", foo2);

function foo1(){ console.log("Hello from foo1"); }
function foo2(){ console.log("Hello from foo2"); }
function foo3(){ console.log("Hello from foo3"); }
<input type="button" value="Click me">