event.preventDefault() 不会在 jQuery Mobile 中取消链接方向



Background
我一直在努力解决这个愚蠢的小问题,即当在jQuery移动应用程序中的锚点元素上触发点击事件时,试图取消链接方向。

假设我有一个简单的多页文档,如下所示:

<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 -->

。和像这样的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));

问题
我只是想不通为什么event.preventDefault()不取消页面过渡。但是,如果我添加event.stopPropagation()它将取消它。另外,如果我从应用程序中删除jQuery移动库,它可以在没有event.stopPropagation()的情况下工作。

问题
这是正常行为吗,是否可以始终在处理程序中调用它们以取消链接方向?

笔记
我使用jQuery Mobile只是因为它的多页模板,导航和过渡功能。

附加问题
潜伏在我最初问题背后的问题是"jQuery Mobile对拦截event.preventDefault()方法的链接做了什么,以阻止链接的默认操作,即转到目标页面。

正常?是的。可以同时打电话吗?是的。
event.preventDefault()是防止浏览器默认行为的唯一工具,event.stopPropagation()是防止触发竞争事件处理程序的唯一工具。

如果你想要一个单行,你可以使用return false来达到相同的结果。从 http://api.jquery.com/on/:

从事件处理程序返回 false 将自动调用 event.stopPropagation() 和 event.preventDefault()。也可以为 handler 作为 function(){ return false; } 的简写。所以 $("a.disabled").on("click", false);将事件处理程序附加到所有 与类"已禁用"的链接,阻止它们被跟踪 当它们被单击时,也会阻止事件冒泡。

我必须承认我对jQuery mobile不太熟悉,但我对此一点也不感到惊讶。我最近为移动设备(纯JS)编写了一些脚本,您注意到的第一件事是大多数设备上完全没有点击事件。现在一切都触手可及

问题是,触摸事件严重过载:当用户触摸屏幕并保持 X 时间时,他可能会尝试选择一些文本,获取放大镜,或者初始触摸可能是滑动的开始。实际上没有要对touchstart执行默认操作。大多数为您提供tab事件的脚本,只需为 touchstart 事件添加一个侦听器,该侦听器将touchend侦听器绑定到 Xbox 的触摸元素,并将其映射到click

阻止默认允许不会停止事件本身,它的默认操作(如果有的话)不会失败,但事件通过 dom 传播,设置了触摸端侦听器,该处理程序将是启动一切的处理程序。如果您不阻止默认操作,而只是阻止事件进一步向下传播到 DOM 中,朝其目标传播,我的猜测是touchout处理程序永远不会被绑定,或者至少永远不会被触发。简而言之:就元素而言,touchstart事件从未到达它,因此如果在没有touchstart的情况下发射touchend,则从未发生过,那一定意味着触摸在DOM的其他地方开始。

我认为,这解释了为什么你会得到这种稍微出乎意料的行为。现在您的问题:

如果没有 jQuery mobile,则会调用点击处理程序。我知道我只是说触摸设备上没有真正的点击事件,但链接会触发直接绑定到元素的点击处理程序。但是,点击事件不能真正在移动设备上委派,只有直接绑定似乎可以解决问题。也许你可以在它们的冒泡阶段抓住它们,但对于锚来说,这确实限制了你的选择。在您的代码段中,您将点击处理程序直接绑定到您的元素,因此这可能只是解释了为什么它适用于常规 jQ,而不是 jQm。

正常行为?是的,我确实相信这一点。根据我的经验,确实如此。是否可以调用这两种方法来停止事件?当然,只要你知道两者之间的区别是什么,并且你知道什么时候以及为什么你只会打电话给1。但是如果你想杀死这个事件,我认为两者都打电话没有坏处。

注意:已经给出的两个答案都说return false;等于同时调用stopPropagationpreventDefault。虽然在jQuery中确实如此,但当你发现自己在编写纯JS时,情况并非如此。在纯JavaScript中,从你的处理程序返回false与只调用preventDefault相同,所以要小心。
一次,MS 的 JScript 实现就是一个很好的例子:

//w3c:
e.preventDefault();
e.stopPropagation();
//IE:
e.returnValue = false;
e.cancelBubble = true;

处理程序返回 false === 事件对象的返回值为 false ,但其冒泡能力保持不变。

最新更新