javascript event.preventDefault() 不会取消 jQuery Mobile 中的链接方向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11994833/
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
event.preventDefault() not canceling link direction in jQuery Mobile
提问by micadelli
Background
I've been struggling with this stupid little problem of trying to cancel link direction when click event is fired on an anchor element in jQuery Mobile app.
背景
我一直在努力解决这个愚蠢的小问题,当点击事件在 jQuery Mobile 应用程序中的锚元素上触发时,试图取消链接方向。
Let's say I have a simple multi-page document like this:
假设我有一个简单的多页文档,如下所示:
<div data-role="page" id="page-1">
<div data-role="content">
<a href="#page-2" id="mLink">page 2</a>
</div><!-- /content -->
</div><!-- /page -->
<div data-role="page" id="page-2">
<div data-role="content">
</div><!-- /content -->
</div><!-- /page -->
... and JavaScript like this:
... 和 JavaScript 是这样的:
(function (MyApp, $, undefined) {
'use strict';
// Initializes app
function init() {
$('#mLink').on('click', function (event) {
event.preventDefault();
//event.stopPropagation();
//event.stopImmediatePropagation();
});
}
// jQuery Mobile is ready now -> override defaults
$(document).on("mobileinit", function () {
// Set the default page transition
$.mobile.defaultPageTransition = 'slide';
});
// jQuery Mobile is ready now
$(document).ready(init);
}(window.MyApp = window.MyApp || {}, jQuery));
Problem
I just can't figure out why event.preventDefault()
isn't canceling the page transition. However, if I add event.stopPropagation()
it will cancel it. Also if I remove the jQuery Mobile library from the app, it works without event.stopPropagation()
.
问题
我就是不明白为什么event.preventDefault()
不取消页面转换。但是,如果我添加event.stopPropagation()
它会取消它。此外,如果我从应用程序中删除 jQuery Mobile 库,它也可以在没有event.stopPropagation()
.
Question
Is this normal behavior and is it ok to always call them both in the handler to cancel the link direction?
问题
这是正常行为吗?总是在处理程序中调用它们以取消链接方向是否可以?
Notes
I'm using jQuery Mobile only for it's multipage template, navigation and transition capabilities.
备注
我使用 jQuery Mobile 只是为了它的多页模板、导航和转换功能。
Additional question
The question lurking behind my original question kind of was 'what jQuery Mobile does to a link that intercepts event.preventDefault() method to notprevent the link's default action, i.e. going to the target page.?'
附加问题
潜伏在我原始问题背后的问题是“jQuery Mobile 对拦截 event.preventDefault() 方法的链接做了什么,以不阻止链接的默认操作,即转到目标页面。?”
回答by Jonathan Wilson
Normal? Yes. OK to call both? Yes.event.preventDefault()
is the only tool you have to prevent the browser's default behavior and event.stopPropagation()
is the only tool you have to prevent competing event handlers from firing.
普通的?是的。两个都打电话好吗?是的。event.preventDefault()
是阻止浏览器默认行为event.stopPropagation()
的唯一工具,也是阻止竞争事件处理程序触发的唯一工具。
If you want a one-liner, you can use return false
to achieve the same result. From http://api.jquery.com/on/:
如果你想要一个单线,你可以使用return false
来达到同样的结果。从http://api.jquery.com/on/:
Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault(). A false value can also be passed for the handler as a shorthand for function(){ return false; }. So, $("a.disabled").on("click", false); attaches an event handler to all links with class "disabled" that prevents them from being followed when they are clicked and also stops the event from bubbling.
从事件处理程序返回 false 将自动调用 event.stopPropagation() 和 event.preventDefault()。也可以为处理程序传递一个 false 值作为 function(){ return false; 的简写;}. 所以, $("a.disabled").on("click", false); 将事件处理程序附加到所有具有“禁用”类的链接,以防止在单击它们时跟踪它们并阻止事件冒泡。
回答by Elias Van Ootegem
I must admit that I'm not too familiar with jQuery mobile, but I'm not at all surprised by this. I've recently written a few script for mobile devices (pure JS) and the first thing you notice is the complete absence of a click event on most of them. Everything is touchnow.
我必须承认,我对 jQuery mobile 不太熟悉,但我对此一点也不感到惊讶。我最近为移动设备(纯 JS)编写了一些脚本,你注意到的第一件事是它们中的大多数完全没有点击事件。现在一切都是触摸。
The thing is, touch events are heavily overloaded: when the user touches the screen and holds for X time, he might be trying to select some text, of get a magnifier, or that initial touch might be the start of a swipe. There isn't really a default action to be taken on touchstart
. Most scripts that offer you a tab
event, just add a listener for a touchstart
event that binds a touchend
listener to the touched element for Xms, and map that to a click
.
问题是,触摸事件严重过载:当用户触摸屏幕并按住 X 时间时,他可能正在尝试选择一些文本、获取放大镜,或者最初的触摸可能是滑动的开始。没有真正要采取的默认操作touchstart
。大多数为您提供tab
事件的脚本,只需为touchstart
事件添加一个侦听器,该事件将touchend
侦听器绑定到 Xms 的触摸元素,并将其映射到click
.
Prevent default allows doesn't stop the event as such, its default action (if any) doesn't fall through, but the event propagates through the dom all the same, the touchend listener is set and that handler will be the one that kicks everything off. If you were not to prevent the default action, but just stop the event from propagating further down the DOM, towards its target, my guess is the touchout
handler never gets bound, or at least never gets fired. Put simply: as far as the element is concerned, the touchstart
event never reached it, so it never occurred if a touchend
is fired without a touchstart
, that must mean the touch started elsewhere in the DOM.
防止默认允许不会停止这样的事件,它的默认操作(如果有的话)不会通过,但是事件通过 dom 传播都是一样的,设置了 touchend 侦听器并且该处理程序将是踢的那个一切都关了。如果您不阻止默认操作,而只是阻止事件进一步向下传播到 DOM,朝向其目标,我的猜测是touchout
处理程序永远不会被绑定,或者至少永远不会被触发。简单地说:就元素而言,touchstart
事件从未到达过它,所以如果 atouchend
被触发而没有 a touchstart
,则它永远不会发生,这意味着触摸在 DOM 的其他地方开始。
That, I think, explains why you get this slightly unexpected behaviour. Now your questions:
我认为,这解释了为什么您会出现这种略微出乎意料的行为。现在你的问题:
Without the jQuery mobile, the click handler is called. I know I just said there is no real click event on touch devices, but links do fire click handlers that are directly bound to the elements. However, the click event can't really be delegated on mobile devices, only direct binding seems to do the trick. Perhaps you might be able to catch them in their bubbling phase, but for anchors, that does limit your options a bit too much. In your snippet, your binding a click handler directly to your element, so that might just explain why it works with regular jQ, and not the jQm.
如果没有 jQuery mobile,则调用单击处理程序。我知道我刚刚说过触摸设备上没有真正的点击事件,但链接确实会触发直接绑定到元素的点击处理程序。然而,点击事件并不能真正委托给移动设备,似乎只有直接绑定才能做到这一点。也许您可以在它们冒泡的阶段抓住它们,但是对于锚点来说,这确实限制了您的选择太多。在您的代码段中,您将点击处理程序直接绑定到您的元素,因此这可能只是解释了为什么它适用于常规 jQ,而不是 jQm。
Normal behaviour? Yes, I do believe so. In my experience it is. Is it ok to call both methods to stop the event? Of course, as long as you know what the difference between the two is, and you know when and why you would call only 1. But if you want to killthe event, I see no harm in calling both.
正常行为?是的,我确实如此相信。根据我的经验是。可以调用这两种方法来停止事件吗?当然,只要您知道两者之间的区别是什么,并且您知道何时以及为什么只调用 1。但是如果您想终止事件,我认为同时调用两者并没有什么坏处。
Note: Both answers already given say that return false;
amounts to the same as calling both stopPropagation
and preventDefault
. While that is true in jQuery, that is NOTthe case when you find yourself writing pure JS. In pure JavaScript returning false from your handler is the same as only calling preventDefault
, so be careful.
For once MS' JScript implementation is a good example of this:
注意:已经给出的两个答案都说这return false;
相当于同时调用stopPropagation
和preventDefault
。虽然这在 jQuery 中是正确的,但当您发现自己在编写纯 JS 时就不是这样了。在纯 JavaScript 中,从处理程序返回 false 与仅调用 相同preventDefault
,因此要小心。
有一次 MS 的 JScript 实现就是一个很好的例子:
//w3c:
e.preventDefault();
e.stopPropagation();
//IE:
e.returnValue = false;
e.cancelBubble = true;
the handler returns false === the event object has a return value of false
, but its ability to bubble is left unchanged.
处理程序返回 false === 事件对象的返回值为false
,但其冒泡能力保持不变。