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

标签 javascript html dom dhtml

HTML 事件属性:

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

使用 HTML DOM 分配事件:
<script>

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

</script>

这两者有什么区别?使用(使用 HTML DOM 分配事件)有什么优势吗?

谢谢

最佳答案

有很大的不同。
通过 HTML 事件属性设置的事件处理程序是我们进行事件处理的第一种方式——在 DOM 出现之前。这种设置事件的方式被称为 DOM Level 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 的对象属性(property)。但是,如果您不知道 Global wrapper(为什么会这样),这将非常令人困惑,因为 this DOM 事件处理程序使用的几乎总是引用导致事件触发的 DOM 元素。
当 DOM Level 1 事件处理规范问世(1998 年)时,一种新的事件配置方式也出现了。我们现在有了代表 HTML 元素的对象,每个对象都有映射到元素属性的属性。出于这个原因,许多人(直到今天)仍然认为使用属性或对象属性在很大程度上是同一回事。但是,有一些重要的区别(I've written about 在我的另一个答案中:参见答案的后半部分),因为属性用于设置值,这可能会影响状态,但属性用于覆盖属性和设置状态。
因此,使用 DOM 事件处理,我们将执行以下操作,您将看到,设置事件回调,不是作为要执行的松散代码,而是通过存储对要在事件发生时调用的函数的引用。因为我们提供了函数,所以它具有我们存储它的 DOM 对象的范围,我们不再需要用 Global 包装松散的命令。这会导致 this绑定(bind)按预期工作:

// 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 事件属性仍然存在一个问题,如果你想设置多个事件处理程序,你没有一个干净的方法来做到这一点,因为你只能在给定的属性中存储一个函数引用。因此,对于现代事件处理,我们使用 .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">

关于javascript - HTML 事件属性和使用 HTML DOM 分配事件有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27905060/

相关文章:

javascript - jQuery 平滑滚动到同一页面和其他页面上的 ID : how to set offset?

javascript - 在 Javascript 中单击文本时 Swal.fire (Sweetalert)

jquery - 如何根据我单击的元素在网页上弹出叠加层?

javascript - 如何使用 Vue.js 更改鼠标悬停时单个列表对象的 html 内容(Font-Awesome Icon)

javascript - 如何检测元素在跨域父级的 iframe 中是否可见

javascript - 在 JavaScript 中访问被 __defineGetter__/__defineSetter__ 隐藏的属性

javascript - Mocha 和应该断言并没有按预期工作

Javascript - 使用 apply 调用绑定(bind)函数

javascript - jQuery 动画排序

javascript - 从 Promises 异步更新 DOM