我想知道 event.preventDefault()
和 return false
是否相同。
我已经完成了some tests,似乎
如果使用旧模型添加事件处理程序,例如 elem.onclick = function(){ return false; };然后,返回 false 会阻止默认操作,例如 event.preventDefault()。
如果使用 addEventListener 添加事件处理程序,例如 elem.addEventListener( 'click', function(e){ return false; }, false );然后, return false 不会阻止默认操作。
所有浏览器的行为都是这样吗?
event.preventDefault()
和 return false
之间是否有更多区别?
我在哪里可以找到一些关于 return false
在某些情况下表现得像 event.preventDefault()
的文档(我在 MDN 中找不到)?
我的问题只是关于纯 javascript,而不是 jQuery,所以请不要将其标记为 event.preventDefault() vs. return false 的副本,即使两个问题的标题几乎相同。
return false
的行为与普通 JavaScript 的行为不同。此外,另一个问题没有任何答案来解释普通 JS 的区别(只有一个解释它的评论,但很难找到)。所以我认为最好有两个不同的问题。
1.3.1 中的 W3C Document Object Model Events Specification。事件注册接口指出 EventListener 中的 handleEvent
没有返回值:
handleEvent 每当发生为其注册了 EventListener 接口的类型的事件时,都会调用此方法。 [...] 没有返回值
在 1.2.4 下。事件取消该文件还指出
取消是通过调用事件的 preventDefault 方法完成的。如果一个或多个 EventListener 在事件流的任何阶段调用 preventDefault,则默认操作将被取消。
这应该会阻止您使用返回 true / false 可能在任何浏览器中产生的任何效果并使用 event.preventDefault()
。
更新
HTML5 规范实际上指定了如何处理不同的返回值。 Section 7.1.5.1 of the HTML Spec 指出
如果返回值为 WebIDL 布尔 false 值,则取消事件。
除了“鼠标悬停”事件之外的所有内容。
结论
我仍然建议在大多数项目中使用 event.preventDefault()
,因为您将与旧规范兼容,从而与旧浏览器兼容。仅当您只需要支持最先进的浏览器时,返回 false 以取消是可以的。
这里有几个例子可以帮助人们更好地理解和解决他们的问题。
TL;博士
on* 事件处理程序(例如按钮元素上的 onclick 属性):返回 false 以取消事件
addEventListener 是一个不同的 API,返回值(例如 false)被忽略:使用 event.preventDefault()。
onclick="
使用浏览器 devtools getEventListeners API 查看事件侦听器的故障处理方式,如果您的事件处理程序未按预期运行。
例子
此示例特定于带有 <a>
链接的 click
事件...但可以概括为大多数事件类型。
我们有一个类 js-some-link-hook
的锚点(链接),我们想要打开一个模式并阻止任何页面导航发生。
以下示例在 MacOS Mojave 上的 google chrome (71) 中运行。
一个主要缺陷是假设 onclick=functionName
与使用 addEventListener
的行为相同
假设我们有一个锚标记(链接),当启用 javascript 时,我们想用 javascript 处理它。我们不希望浏览器在单击时跟随链接(“防止默认”行为)。
<a href="https://www.example.com/url/to/go/to/when/no/javascript"
class="js-some-link-hook">click me!</a>
onclick 属性
function eventHandler (event) {
// want to prevent link navigation
alert('eventHandler ran');
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.setAttribute('onclick', eventHandler);
}
addEventListenerToElement();
然后在浏览器 devtools 控制台中运行:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
...你会看到:
function onclick(event) {
function eventHandler (event) {alert('eventHandler ran'); return false;}
}
这根本行不通。使用 onclick=
时,您的处理函数被包装在另一个函数中。
您可以看到我的函数定义包含在但没有被调用,因为我指定了函数引用而没有调用它。即我们需要 onclick="functionName()"
而不是 onclick="functionName"
来确保在单击元素时运行 functionName
。
此外,您可以看到,即使我的函数被调用并且我的函数返回 false...onclick
函数不会返回该 false 值...这是“取消”事件所必需的。
为了解决这个问题,我们可以将 onclick
设置为 return myHandlerFunc();
,以确保 onclick
从 myHandlerFunc
返回返回值 (false)。
您也可以从 myHandlerFunc
中删除 return false;
并将 onclick
更改为 myHandlerFunc(); return false;
但这不太有意义,因为您可能希望将逻辑保持在处理函数中。
请注意,使用 javascript 设置 onclick
时,当您直接在 html 中设置 onclick
而不是使用 javascript(如我的示例)时,onclick
属性值是字符串类型,一切正常。如果您使用 javascript 设置 onclick
,则需要注意类型。如果您说 element.setAttribute('onclick', myHandlerFunc())
myHandlerFunc
将立即运行,结果将存储在属性中...而不是在每次点击时运行。相反,您应该确保将属性值设置为字符串。 element.setAttribute('onclick', 'return myHandlerFunc();')
现在我们看到了它是如何工作的,我们可以修改代码来做任何我们想做的事情。用于说明目的的奇怪示例(不要使用此代码):
function eventHandler (e) {
// want to prevent link navigation
alert('eventHandler ran');
console.log(e);
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.setAttribute('onclick', 'return ('+eventHandler+')(event);');
}
addEventListenerToElement();
您会看到我们已将 eventHandler 函数定义包装到字符串中。具体来说:一个在前面带有return语句的自执行函数。
再次在 chrome devtools 控制台中:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
...显示:
function onclick(event) {
return (function eventHandler (e) {
// want to prevent link navigation
alert('eventHandler ran');
console.log(e);
return false;
})(event);
}
......所以是的,这应该工作。果然,如果我们单击链接,我们会收到警报并关闭该页面无法导航或刷新的警报。
关于 onclick
的更多说明... 如果您想在事件发生时接收和使用 event
参数,您应该注意它被命名为“事件”。您可以在处理程序中使用名称 event
访问它(可通过父 onclick
函数范围获得)。或者您可以构造您的处理程序以将 event
作为参数(更适合测试)...例如 onclick="return myEventHandler(event);"
或如您在前面的示例中看到的那样。
添加事件监听器
function eventHandler (ev) {
// want to prevent link navigation
alert('eventHandler ran');
console.log(ev);
return false;
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();
浏览器开发工具:
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
结果:
function eventHandler (ev) {
// want to prevent link navigation
alert('eventHandler ran');
console.log(ev);
return false;
}
所以你已经可以看出区别了。对于 addEventListener
,我们没有被包装在 onclick
函数中。我们的处理程序直接接收 event
参数(因此我们可以随意调用它)。此外,我们的 return false
在这里处于“顶层”,我们不必担心像 onclick
那样添加额外的 return 语句。
所以看起来它应该工作。单击链接,我们会收到警报。关闭警报,页面导航/刷新。即事件没有通过返回false来取消。
如果我们查找规范(参见底部的资源),我们会看到 addEventListener 的回调/处理函数不支持返回类型。我们可以返回任何我们想要的,但由于它不是浏览器 API/接口的一部分,它没有任何效果。
解决方案:使用 event.preventDefault()
而不是 return false;
...
function eventHandler (ev) {
// want to prevent link navigation
ev.preventDefault();
alert('eventHandler ran');
}
function addEventListenerToElement () {
var link = document.querySelector('.js-some-link-hook');
link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();
浏览器开发工具...
var el = document.querySelector('a.js-some-link-hook'),
listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output
给...
function eventHandler (ev) {
// want to prevent link navigation
ev.preventDefault();
alert('eventHandler ran');
}
...正如预期的那样。
再次测试:
点击链接。
得到警报。
解除警报。
没有页面导航或刷新发生......这是我们想要的。
因此,使用 addEventListener
使用 event.preventDefault()
作为返回 false 什么都不做。
资源
https://www.w3.org/TR/dom41/#dom-eventtarget-addeventlistener 事件注册(例如 addEventListener)
事件注册(例如 addEventListener)
https://www.w3.org/TR/dom41/#callbackdef-eventlistener callback/handler/listener def。注意返回类型是无效的。即返回值不是接口的一部分,没有任何作用。
回调/处理程序/侦听器定义。
注意返回类型是无效的。即返回值不是接口的一部分,没有任何作用。
https://www.w3.org/TR/dom41/#event 事件对象(例如 Event.preventDefault)
事件对象(例如 Event.preventDefault)
html5 规范 (https://www.w3.org/TR/html5/webappapis.html#events) 使事情变得混乱,因为他们在示例中同时使用了 onclick
和 addEventListener
,并且他们说如下:
事件处理器H和Event对象E的事件处理器处理算法如下: ... 处理返回值如下: ... 如果返回值为Web IDL boolean false 值,则取消该事件。
因此,这似乎暗示 return false
取消了 addEventListener
和 onclick
的事件。
但是,如果您查看他们对 event-handler
的链接定义,您会看到:
事件处理程序有一个名称,该名称始终以“on”开头,后跟它所针对的事件的名称。 ...事件处理程序以两种方式之一公开。第一种方式,所有事件处理程序共有的,是作为事件处理程序 IDL 属性。第二种方式是作为事件处理程序内容属性。 HTML 元素上的事件处理程序和 Window 对象上的一些事件处理程序以这种方式公开。
https://www.w3.org/TR/html5/webappapis.html#event-handler
因此,似乎 return false
取消事件确实只适用于 onclick
(或通常为 on*
)事件处理程序,而不适用于通过具有不同 API 的 addEventListener
注册的事件处理程序。
由于 html5 规范未涵盖 addEventListener
API(仅 on*
事件处理程序)...如果他们在示例中坚持使用 on*
样式的事件处理程序,就会减少混乱。
preventDefault、stopPropogation、return false 之间的区别
https://i.stack.imgur.com/FGEbh.png
默认操作 – 控制事件引发时的服务器端操作。
假设我们有 div 控件,并且在其中我们有一个按钮。所以 div 是按钮的父控件。我们有按钮的客户端单击和服务器端单击事件。我们还有 div 的客户端点击事件。
在客户端按钮的点击事件中,我们可以通过以下三种方式控制父控件和服务器端代码的动作:
return false - 这仅允许控件的客户端事件。不触发父控件的服务器端事件和客户端事件。
preventDefault() - 这允许控制的客户端事件及其父控件。服务器端事件,即。不触发控件的默认操作。
stopPropogation() – 这允许控件的客户端和服务器端事件。不允许控件的客户端事件。
return false
不会停止传播,因此会触发父控件 (demo)。此外,我不确定“服务器端点击事件”是什么意思。
return false
仅适用于 IE,event.preventDefault()
受 chrome 支持,ff...现代浏览器
return false
的工作方式与 event.preventDefault()
类似
stopPropagation()
、preventDefault()
和return false
的行为:jsfiddle.net/m1L6of9x。在现代浏览器上,后两者具有相同的行为。