2

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

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

<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 Mobile 库,它可以在没有event.stopPropagation().

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

备注
我使用 jQuery Mobile 只是因为它的多页模板、导航和转换功能。

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

4

2 回答 2

6

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

如果你想要一个单线,你可以使用return false来达到同样的效果。来自http://api.jquery.com/on/

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

于 2012-08-16T20:23:23.317 回答
3

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

问题是,触摸事件严重超载:当用户触摸屏幕并按住 X 时间时,他可能正在尝试选择一些文本,或者拿放大镜,或者最初的触摸可能是滑动的开始。没有真正要采取的默认操作touchstart。大多数为您提供tab事件的脚本,只需为将侦听器touchstart绑定touchend到 Xms 的触摸元素的事件添加侦听器,并将其映射到click.

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

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

如果没有 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,但它的冒泡能力保持不变。

于 2012-08-16T20:58:59.270 回答