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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18971284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 13:54:18  来源:igfitidea点击:

event.preventDefault() vs. return false (no jQuery)

javascripteventsevent-handlingdom-eventspreventdefault

提问by Oriol

I wondered if event.preventDefault()and return falsewere the same.

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

I have done some tests, and it seems that

我做了一些测试,似乎

  • If the event handler is added using old model, for example

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

    Then, return falseprevents default action, like event.preventDefault().

  • If the event handler is added using addEventListener, for example

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

    Then, return falsedoesn't prevent the default action.

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

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

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

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

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

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

Do all browsers behave like this?

所有浏览器都这样吗?

Are there more differences between event.preventDefault()and return false?

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

Where I can find some documentation (I couldn't in MDN) about return falsebehaving like event.preventDefault()in some cases?

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



My question is only about plain javascript, not jQuery, so please don't mark it as a duplicate of event.preventDefault() vs. return false, even if both questions have almost the same title.

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

采纳答案by Thorben Croisé

The W3C Document Object Model Events Specificationin 1.3.1. Event registration interfacesstates that handleEventin the EventListener has no return value:

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

handleEventThis method is called whenever an event occurs of the type for which the EventListener interface was registered. [...] No Return Value

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

under 1.2.4. Event Cancelationthe document also states that

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

Cancelation is accomplished by calling the Event's preventDefault method. If one or more EventListeners call preventDefault during any phase of event flow the default action will be canceled.

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

which should discourage you from using any effect that returning true / false could have in any browser and use event.preventDefault().

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

Update

更新

The HTML5 spec actually specifies how to treat a return value different. Section 7.1.5.1 of the HTML Specstates that

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

If return value is a WebIDL boolean false value, then cancel the event.

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

for everything but the "mouseover" event.

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

Conclusion

结论

I would still recommend to use event.preventDefault()in most projects since you will be compatible with the old spec and thus older browsers. Only if you only need to support cutting edge browsers, returning false to cancel is okay.

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

回答by mattpr

Here are a few examples that might help people to understand and troubleshoot their problems better.

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

TL;DR

TL; 博士

  • on*event handlers (e.g. onclickattribute on a button element): return false to cancel event
  • addEventListeneris a different API, return values (e.g. false) are ignored: use event.preventDefault().
  • onclick="<somejs>"has its own potential confusion because <somejs>is wrapped into the body of an onclick function.
  • Use the browser devtools getEventListenersAPI to see what your event listener looks like to troubleshoot if your event handler is not behaving as expected.
  • on*事件处理程序(例如onclick按钮元素上的属性):返回 false 以取消事件
  • addEventListener是一个不同的 API,返回值(例如false)被忽略:使用event.preventDefault()
  • onclick="<somejs>"有它自己的潜在混淆,因为它<somejs>被包裹在一个 onclick 函数的主体中。
  • getEventListeners如果您的事件处理程序没有按预期运行,请使用浏览器 devtools API 查看您的事件侦听器如何进行故障排除。

Example

例子

This example is specific to the clickevent with an <a>link...but can be generalized for most event types.

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

We have an anchor (link) with class js-some-link-hookthat we want to open a modal and prevent any page navigation from happening.

我们有一个带有类的锚点(链接)js-some-link-hook,我们希望打开一个模态并防止任何页面导航发生。

The below examples were run in google chrome (71) on MacOS Mojave.

以下示例在 MacOS Mojave 上的 google chrome (71) 中运行。

One major pitfall is assuming that onclick=functionNameis the same behaviour as using addEventListener

一个主要的陷阱是假设这onclick=functionName与使用相同的行为addEventListener

onclick attribute

点击属性

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();

Then run in the browser devtools console:

然后在浏览器的 devtools 控制台中运行:

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
    console.log(''+listener); // to avoid truncation of output

...and you see:

......你会看到:

function onclick(event) {
function t(n){return alert("eventHandler ran"),!1}
}

This doesn't work at all. When using onclick=your handler function is wrapped in another function. In this case you can see that my function definition is included but not called because I specified the function reference without invoking it. Further you can see that even if my function was invoked and my function returned false...the onclick function would not return that false value...which is required to 'cancel' the event. We really need return myHandlerFunc();to be wrapped in the onclick function for things to work.

这根本行不通。使用时,onclick=您的处理程序函数被包装在另一个函数中。在这种情况下,您可以看到我的函数定义被包含但未被调用,因为我指定了函数引用而没有调用它。此外,您可以看到,即使调用了我的函数并且我的函数返回了 false……onclick 函数也不会返回那个 false 值……这是“取消”事件所必需的。我们真的需要return myHandlerFunc();被包裹在 onclick 函数中才能工作。

Now that we see how that is working, we can modify the code to do whatever we want. Odd example for illustration purposes (don't use this code):

现在我们看到了它是如何工作的,我们可以修改代码来做我们想做的任何事情。用于说明目的的奇怪示例(不要使用此代码):

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', 'return ('+eventHandler+')();');
}
addEventListenerToElement();

You see we have wrapped our eventHandler function definition into string. Specifically: a self-executing function with a return statement at the front.

您会看到我们已将 eventHandler 函数定义包装到字符串中。具体来说:一个前面带有return语句的自执行函数。

Again in chrome devtools console:

再次在 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

...shows:

...显示:

function onclick(event) {
return (function t(e){return alert("eventHandler ran"),!1})();
}

...so yeah, that should work. Our return false(!1due to minification running, sorry). Sure enough if we click on the link we get the alert and dismissing the alert the page doesn't navigate anywhere or refresh.

......所以是的,这应该有效。我们的return false!1由于正在运行,抱歉)。果然,如果我们点击链接,我们会收到警报并解除警报,页面不会导航到任何地方或刷新。

addEventListener

添加事件监听器

function eventHandler (event) {
    // want to prevent link navigation
    alert('eventHandler ran');
    return false;
}

function addEventListenerToElement () {
    var link = document.querySelector('.js-some-link-hook');
    link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();

browser devtools:

浏览器开发工具:

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
    console.log(''+listener); // to avoid truncation of output

result:

结果:

function e(n){return alert("eventHandler ran"),!1}

So you can already see the difference. We aren't wrapped in an onclick function. So our return false(return !1due to minification) is at the top level here and we don't have to worry about adding an extra return statement like before.

所以你已经可以看出区别了。我们没有包含在 onclick 函数中。所以我们的return falsereturn !1由于缩小)在这里处于顶层,我们不必担心像以前一样添加额外的 return 语句。

So it looks like it should work. Clicking on the link we get the alert. Dismiss the alert and the page navigates/refreshes. ie the event was NOT cancelled by returning false.

所以看起来它应该工作。单击链接,我们会收到警报。解除警报,页面导航/刷新。 即事件没有通过返回 false 取消。

If we lookup the spec (see resources at bottom), we see that our callback/handler function for addEventListener does not support a return type. We can return whatever we want, but since it isn't part of the interface, it doesn't have any effect.

如果我们查找规范(请参阅底部的资源),我们会发现 addEventListener 的回调/处理程序函数不支持返回类型。我们可以返回任何我们想要的东西,但由于它不是接口的一部分,所以它没有任何作用。

Solution: using event.preventDefault()instead of return false;...

解决方案:使用event.preventDefault()代替return false;...

function eventHandler (event) {
    // want to prevent link navigation
    event.preventDefault();
    alert('eventHandler ran');
}

function addEventListenerToElement () {
    var link = document.querySelector('.js-some-link-hook');
    link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();

browser devtools...

浏览器开发工具...

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
    console.log(''+listener); // to avoid truncation of output

gives...

给...

function n(e){e.preventDefault(),alert("eventHandler ran")}

...as expected.

...正如预期的那样。

Testing: get the alert. Dismiss alert. Nopage navigation or refresh...which is what we want.

测试:获取警报。解除警报。 没有页面导航或刷新......这就是我们想要的。

Resources

资源

The html5 spec (https://www.w3.org/TR/html5/webappapis.html#events) confuses things because they use both onclickand addEventListenerin their examples and they say the following:

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

The event handler processing algorithm for an event handler H and an Event object E is as follows:

...

  1. Process return value as follows:

...

If return value is a Web IDL boolean false value, then cancel the event.

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

...

  1. 处理返回值如下:

...

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

So it seems to imply that return falsecancels the event for both addEventListenerand onclick.

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

But, if you look at their linked definition of event-handleryou see:

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

An event handler has a name, which always starts with "on" and is followed by the name of the event for which it is intended.

...

Event handlers are exposed in one of two ways.

The first way, common to all event handlers, is as an event handler IDL attribute.

The second way is as an event handler content attribute. Event handlers on HTML elements and some of the event handlers on Window objects are exposed in this way.

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

...

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

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

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

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

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

So it seems that the return falsecancelling the event really does only apply to the onclick(or generally on*) event handlers and not to event handlers registered via addEventListenerwhich has a different API. Since the addEventListener API is not covered under the html5 spec and only the on*event handlers...it would be less confusing if they stuck to that in their examples and specifically called out the difference.

因此,return false取消事件似乎确实仅适用于onclick(或通常on*)事件处理程序,而不适用于通过addEventListener具有不同 API注册的事件处理程序。由于 addEventListener API 未包含在 html5 规范中,而仅包含on*事件处理程序……如果他们在示例中坚持这一点并特别指出差异,那么就不那么令人困惑了。

回答by Rahul Shinde

Difference between preventDefault, stopPropogation, return false

preventDefault, stopPropogation, return false 的区别

Table Showing Difference

表显示差异

Default Action – Server side action when control event raise.

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

Suppose we have div control and inside it we have a button. So div is the parent control of the button. We have Client side click and server side click event of the button. Also we have client side click event of the div.

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

On click event of the button on client side, we can control the actions of parent control and server side code using following three ways:

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

  • return false- This allow only client side event of the control. Server side event and client side event of the parent control is not fired.

  • preventDefault()- This allow client side event of control and its parent control. Server side event ie. Default action of the control is not fired.

  • stopPropogation()– This allow client side as well as server side event of the control. Client side event of the control is notallowed.

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

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

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

回答by ppy

return falseis just for IE, event.preventDefault()is supported by chrome,ff... modern browsers

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