2

我试图了解 jQueryMobile 导航中的页面事件,但我发现了一些非常奇怪的行为,因为一些事件处理程序被多次调用:

我有两个页面:home.html 和 disclaimer.html。两者都包含相同的标题:

<head>
    <script src="js/jquery-1.8.2.min.js"></script>
    <script src="js/events.js"></script>
    <script src="js/jquery.mobile-1.2.0.min.js"></script>
</head>

在 home.html 页面上有一个链接:

<section data-role="page" id="home">
    <a href="#" id="test">Test</a>
</section>

在文件 events.js 中是以下代码:

var i = 0;

$(document).on('pageinit', 'section#home', function(event) {
    console.log(i++, 'pageinit');
    $('a#test').on('click', function() {
        console.log(i++, 'click pageinit');
    });
});

$(document).on('pagebeforeshow', 'section#home', function(event) {
    console.log(i++, 'pagebeforeshow');
    $('a#test').on('click', function() {
        console.log(i++, 'click pagebeforeshow');
    });
});

然后我执行以下步骤:

  1. 导航到 home.html (http)
  2. 点击链接
  3. 转到 disclaimer.html (ajax)
  4. 转到 home.html (ajax)
  5. 点击链接

使用以下控制台输出:

0 "pageinit"             // step 1
1 "pagebeforeshow"
2 "click pageinit"       // step 2
3 "click pagebeforeshow"
4 "pagebeforeshow"       // step 4
5 "click pageinit"       // step 5
6 "click pagebeforeshow"
7 "click pagebeforeshow" 

有道理,对吧?但现在奇怪的部分。当我更改访问页面的顺序时:行为会发生变化。

  1. 导航到 disclaimer.html (http)
  2. 转到 home.html (ajax)
  3. 点击链接
  4. 转到 disclaimer.html (ajax)
  5. 转到 home.html (ajax)
  6. 点击链接

控制台输出:

0 "pageinit"             // step 2
1 "pagebeforeshow"
2 "click pageinit"       // step 3
3 "click pagebeforeshow"
4 "pageinit"             // step 5
5 "pagebeforeshow"
6 "click pageinit"       // step 6
7 "click pagebeforeshow" 

这很奇怪,因为我希望第 6 个和第 7 个结果被重复。

对不起,很长的问题。我希望有人能准确地向我解释发生了什么,如果这是预期的行为?

tldr; 你在哪里监听 jQueryMobile 中的(点击)事件?

4

1 回答 1

1

简而言之:在 jQueryMobile 中,你应该在里面监听(绑定)你的事件pageinit;这相当于(或多或少)jQuery 的ready事件。这是jQueryMobile的人推荐的。

pageinit一旦页面被加载和初始化(通过 AJAX 或 HTTP)触发,但pagebeforeshow如果页面已经在 DOM 中,可能会被触发多次,例如在关闭 jQueryMobile 对话框之后。每次再次显示页面时,您绑定的任何pagebeforeshow内容都会再次重新绑定。这就是为什么你有两次点击 pagebeforeshow

编辑:你的测试的解释

我复制了您的 2 个 html 页面和 js 文件,并在两个测试中重复了所有步骤。

在您的第一次测试中,您有:

  1. 导航到 home.html (http):它绑定(通过委托文档)和触发器pageinitpagebeforeshow(日志 0 和 1),因为您的页面已初始化并将显示。这还将其他两个函数绑定到链接(重要:在这种情况下不是委托,而是直接绑定!)。这是该测试中唯一一次加载和执行“events.js”。
  2. 单击链接:这会按预期执行click pageinitclick pagebeforeshow(日志 2 和 3),因为步骤 1。
  3. 转到 disclaimer.html (ajax):这不显示任何日志。
  4. 转到 home.html (ajax):因为“home.html”仍在 DOM 中,这会触发pagebeforeshow,正如您在日志 (4) 中看到的那样。这也会执行链接中的绑定。注意:我怀疑在此步骤中“disclaimer.html”已从 DOM 中删除(在第二次测试中对此进行了更多介绍)。
  5. 单击链接:显示树日志,前 2 个因为第 1 步,最后一个(重复)因为第 4 步。

在您的第二次测试中,您有:

  1. 导航到 disclaimer.html (http):它绑定pageinitpagebeforeshow,但不显示日志,因为没有触发任何事件;这两个事件都被绑定到document(通过委托),所以如果特定页面还没有在 DOM 中并不重要。这是该测试中唯一一次加载和执行“events.js”。
  2. 转到 home.html (ajax):它触发pageinit并且pagebeforeshow您可以看到日志 0 和 1。当两个事件都被触发时,相应的点击事件被绑定到链接(直接绑定!)
  3. 单击链接:此步骤按预期显示日志 2 和 3。
  4. 转到 disclaimer.html (ajax):日志中没有显示任何内容......但是:jQueryMobile 决定应该从 DOM 中删除“home.html”!这是因为一旦您导航到另一个页面,JQM 就会删除每个页面。请注意,“disclaimer.html”永远不会从 DOM 中删除,因为他是它的“所有者”。
  5. 转到 home.html (ajax):这一步触发pageinitpagebeforeshow(因为这两个事件仍然绑定到文档对象),如您在日志 4 和 5 中所见。这将两个函数绑定到链接,就像在步骤 2 中一样,但是...(见下一步)
  6. 点击链接:这里是你说“我希望第 6 和第 7 个结果被重复”的地方;好吧,它们没有被复制,因为整个页面(包含链接的 div)及其所有内容都已从 DOM 中删除,并且您直接绑定到链接的第一次点击事件(在步骤 2 中)都消失了!因此您只能看到由步骤 5 中的绑定引起的日志。

如果我(最终)理解了 JQM 事件的工作原理,则加载的第一个页面(通过完整的 HTTP 请求)将保留在 DOM 中,直到用户导航到外部页面或重新加载页面(通过 F5 或 CTRL+R)。任何其他页面(通过 AJAX 加载)都会添加到“主”DOM,然后在您导航到另一个页面时从其中卸载/删除。因此:如果您在pageinit(直接绑定或最多委托给其父 div[data-role:page])中进行所有绑定,则无需担心重复的事件绑定。

PD:如果你注意到我的写作方式有些奇怪,可能是因为我不习惯用被动语态用英语说/写,有时我会混淆介词:P

于 2012-12-07T02:10:10.017 回答