event.preventDefault() 与返回 false(无 jQuery)

IT技术 javascript events event-handling dom-events preventdefault
2021-01-12 09:38:40

我想知道event.preventDefault()return false是否相同。

我做了一些测试,似乎

  • 例如,如果使用旧模型添加事件处理程序

    elem.onclick = function(){
        return false;
    };
    

    然后,return false阻止默认操作,例如event.preventDefault().

  • 如果事件处理程序使用添加addEventListener,例如

    elem.addEventListener(
        'click',
        function(e){
            return false;
        },
        false
    );
    

    然后,return false不会阻止默认操作。

所有浏览器都这样吗?

event.preventDefault()之间有更多区别return false吗?

我在哪里可以找到一些关于某些情况下return false行为的文档(我在 MDN 中找不到)event.preventDefault()


我的问题只是关于普通的 javascript,而不是 jQuery,所以请不要将其标记为event.preventDefault() 与 return false的重复,即使两个问题的标题几乎相同。

4个回答

W3C文档对象模型事件规范1.3.1。事件注册接口声明handleEvent在 EventListener 中没有返回值:

handleEvent 每当发生注册 EventListener 接口的类型的事件时,都会调用此方法。[...]无返回值

根据1.2.4。事件取消文件还指出

取消是通过调用事件的 preventDefault 方法完成的。如果一个或多个 EventListeners 在事件流的任何阶段调用 preventDefault,则默认操作将被取消。

这应该会阻止您使用返回 true / false 可能在任何浏览器中产生的任何效果并使用event.preventDefault().

更新

HTML5 规范实际上指定了如何处理不同的返回值。HTML 规范的第 7.1.5.1 节指出

如果返回值为 WebIDL boolean false 值,则取消该事件。

除了“鼠标悬停”事件之外的所有内容。

结论

我仍然建议event.preventDefault()在大多数项目中使用,因为您将与旧规范兼容,因此与旧浏览器兼容。只有当你只需要支持尖端浏览器时,返回 false 取消是可以的。

这拨弄比较的行为stopPropagation()preventDefault()以及return falsejsfiddle.net/m1L6of9x在现代浏览器上,后两者具有相同的行为。
2021-04-08 09:38:40
从 chrome 中的一些快速测试来看, return false 和 event.preventDefault() 都不会停止传播。主要归功于@Oriol:参见停止传播正常
2021-04-09 09:38:40
此链接写于 2000 年。 HTML5 规范:w3.org/TR/html5/webappapis.html#event-handler-attributes看起来像处理许多事件的返回值(不是鼠标悬停):“如果返回值是 WebIDL 布尔值假值,则取消事件”
2021-04-10 09:38:40

以下是一些可能有助于人们更好地理解和解决问题的示例。

TL; 博士

  • on*事件处理程序(例如onclick按钮元素上的属性):返回 false 以取消事件
  • addEventListener是一个不同的 API,返回值(例如false)被忽略:使用event.preventDefault()
  • onclick="<somejs>"有它自己的潜在混淆,因为它<somejs>被包裹在一个 onclick 函数的主体中。
  • getEventListeners如果您的事件处理程序没有按预期运行,请使用浏览器 devtools API 查看您的事件侦听如何进行故障排除。

例子

此示例特定于click带有<a>链接事件...但可以推广到大多数事件类型。

我们有一个带有类的锚点(链接)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>

点击属性

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 值……这是“取消”事件所必需的。

为了解决这个问题,我们可以设置onclickreturn myHandlerFunc();which 确保从onclick返回返回值 (false) myHandlerFunc

您也可以删除return false;frommyHandlerFunc并将其更改onclick为 be ,myHandlerFunc(); return false;但这没有意义,因为您可能希望将逻辑保持在处理程序函数中。

请注意,onclick使用 javascript进行设置时,当您onclick直接在 html 中而不是使用 javascript进行设置时(如我的示例),onclick属性值为 string 类型并且一切正常。如果你onclick使用javascript设置,你需要注意类型。如果您说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在这里处于“顶级”,我们不必担心添加额外的 return 语句,例如 with onclick

所以看起来它应该工作。单击链接,我们会收到警报。解除警报,页面导航/刷新。 即事件没有通过返回 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()as 返回 false 什么都不做。

资源

html5 规范 ( https://www.w3.org/TR/html5/webappapis.html#events ) 混淆了事情,因为他们在他们的示例中同时使用onclickaddEventListener并且他们说如下:

一个事件处理器H和一个Event对象E的事件处理器处理算法如下:

...

  1. 处理返回值如下:

...

如果返回值为 Web IDL boolean false 值,则取消该事件。

因此,它似乎暗示,return false取消两个事件addEventListeneronclick

但是,如果您查看他们的链接定义,event-handler您会看到:

事件处理程序有一个名称,该名称始终以“on”开头,后跟要处理的事件的名称。

...

事件处理程序以两种方式之一公开。

第一种方式,对所有事件处理程序通用,是作为事件处理程序 IDL 属性。

第二种方式是作为事件处理程序的内容属性。HTML 元素上的事件处理程序和 Window 对象上的一些事件处理程序以这种方式公开。

https://www.w3.org/TR/html5/webappapis.html#event-handler

因此,return false取消事件似乎确实仅适用于onclick(或通常on*)事件处理程序,而不适用于通过addEventListener具有不同 API注册的事件处理程序

由于addEventListenerhtml5 规范未涵盖 API(仅包含on*事件处理程序)……如果他们坚持使用on*示例中样式事件处理程序,就不会那么混乱

preventDefault, stopPropogation, return false 的区别

表显示差异

默认操作 - 控件事件引发时的服务器端操作。

假设我们有 div 控件并且在它里面有一个按钮。所以div是按钮的父控件。我们有按钮的客户端单击和服务器端单击事件。我们还有 div 的客户端点击事件。

在客户端按钮的点击事件中,我们可以通过以下三种方式来控制父控件和服务器端代码的动作:

  • return false- 这仅允许控件的客户端事件。不会触发父控件的服务器端事件和客户端事件。

  • preventDefault()- 这允许控件及其父控件的客户端事件。服务器端事件即。不会触发控件的默认操作。

  • stopPropogation()– 这允许控件的客户端和服务器端事件。控件的客户端事件是不允许的。

关于服务器端事件的废话是什么?-1
2021-03-21 09:38:40
@初学者,请忽略此答案。
2021-03-27 09:38:40
在谈论 JavaScript 和事件时,没有“服务器端”。
2021-03-29 09:38:40
我认为服务器端的东西正在考虑 ASP,您可以在服务器上处理事件。
2021-04-03 09:38:40
你错了,return false不会停止传播,所以父控件被触发(演示)。此外,我不确定“服务器端点击事件是什么意思
2021-04-07 09:38:40

return false仅适用于 IE,event.preventDefault()支持 chrome,ff...现代浏览器

但是在 Firefox 上的return false工作方式就像event.preventDefault()使用旧模型添加事件处理程序一样
2021-03-31 09:38:40