【问题标题】:Moving from page to page creates errors (duplicates?)从一个页面移动到另一个页面会产生错误(重复?)
【发布时间】:2016-12-07 20:00:24
【问题描述】:

我正在尝试使用 OnsenUI 2 的 pushPage() 功能(截至目前为 rc15)。除了 OnsenUI,我还在使用 jQuery 3。

这是我的功能,点击某些元素时应该推送一个页面:

$(".tile_handler").on("click", ".imalink", function () {
    var link = $(this).data().href;
    if(link != null){
        document.querySelector("#myNavigator").pushPage(link, { animation: "slide-ios" });
    }
})

当我第一次推送页面时,它工作正常。我使用 iOS 后退按钮返回。然后我再次点击它,我得到了这个错误(随着我重复这个过程越来越多):

[index.js:450] 未捕获(承诺)pushPage 已经在运行。

这是另一个应该加载拆分页面的函数:

$(".splitter_item").click(function () {
    var address = $(this).data('address');
    $('#content')[0].load(address).then(menu.close.bind($('#menu')[0]));
})

当我通过拆分器在两个页面之间切换时,它开始抛出这个(每次我在页面之间切换时都会抛出更多)

[undefined:1] Uncaught (in promise) Splitter 端被锁定。


我假设正在发生的事情是我加载了一个页面,然后离开它,当我再次访问它时,它再次加载了该页面。然而,这似乎不是 OnsenUI 示例中显示的行为,例如 as this

document.addEventListener('init', function(event) {
  var page = event.target;

  if (page.id === 'page1') {
    page.querySelector('#push-button').onclick = function() {
      document.querySelector('#myNavigator').pushPage('page2.html', {data: {title: 'Page 2'}});
    };
  } else if (page.id === 'page2') {
    page.querySelector('ons-toolbar .center').innerHTML = page.data.title;
  }
});

popPage() 函数应该删除以前加载的页面并防止这种情况发生。但是参考文献没有使用它,所以我认为我做错了什么。但我不知道是什么。


更新

我设法在 CodePen 中重现了这两个问题。 Here 是拆分器错误,herepushPage() 之一。 pushPage() 似乎是我的函数的一个问题,因为它每次单击它时都会添加一个 pushPage() 请求,但不知道为什么。

这两个错误似乎只发生在 Ripple 模拟器中(通过 VS2015)。我似乎无法在 Android Emulator 中重现它们(但 $(".tile_handler").on("click", ".imalink", function () { 代码无论如何都会多次触发错误)。我正在进一步测试。

【问题讨论】:

  • 您可以一遍又一遍地推送同一页面而不会出现问题。我做了一个快速的 codepen:codepen.io/anon/pen/NALzWZ 证明了这一点。后退按钮确实执行了 popPage() 但如您所见,我一遍又一遍地将相同的 page2.html 模板推送到导航堆栈而没有问题。通常,当我收到或看到该错误时,会发生其他事情。
  • 这种情况只发生在 iOS 上还是在浏览器上?如果你使用fade-ios动画也会发生这种情况吗?
  • 我的装备有点不足,所以我现在只有模拟器可以使用。这发生在 Android 和 iOS 上的 Ripple Emulator 中。我添加了一个重现错误的 CodePen。

标签: javascript jquery cordova onsen-ui onsen-ui2


【解决方案1】:

基本上每次推送页面时,该页面都会触发init 事件。但是 Onsen 仍然将初始页面保留在 dom 中。

导航器示例(同样的逻辑适用于拆分器):

<ons-navigator>
  <ons-page id="dashboard">
    <div class="imalink" data-href="request_list.html"></div>
  </ons-page>
</ons-navigator>

您有一个仪表板的初始化事件。然后单击该图块并转到另一个页面。 然后request_list 触发它自己的init 事件。但是我们的初始页面仍然在 dom 中。

<ons-navigator>
  <ons-page id="dashboard" style="display: none">
    <div class="imalink" data-href="request_list.html"></div>
  </ons-page>
  <ons-page id="request_list">
    ...
  </ons-page>
</ons-navigator>

你有这样的东西。但是第二次调用以下内容:

$(".tile_handler").on("click", ".imalink", function () {
  ...
})

这又增加了听众。 $el.on("click") 就像addEventListener 的别名,意味着你正在添加越来越多的听众。

因此,每当您导航时,您都会不断添加它们,因为初始页面从未从 dom 中删除。

替代解决方案:

  1. 仅使用当前页面 (e.target)

    $('selector') // instead of this   
    $(e.target).find('selector')  // use this
    

    这样,您只能在刚刚创建的页面中查找元素。

  2. 从一开始就启用处理程序。 由于您使用的是 jQuery,因此实际上有一种更简单的方法来做这些事情,而无需依赖 init 事件。

    只需在任何初始化处理程序之外执行此操作:

    $(document).on("click", ".tile_handler .imalink", function () { ... })
    

    这实际上意味着处理程序附加到文档本身,并且仅当目标为 .tile_handler .imalink 时才会调用处理程序 - 因此它适用于您创建的任何未来 imalink。

    这可能不是最有效的方法,但绝对是最简单的方法之一。

【讨论】:

  • 我现在明白了。谢谢!
【解决方案2】:

您提到的两个错误实际上是一种安全措施,例如,如果您双击按钮/链接,您会错误地推动或执行某些操作两次。

当您在动画运行时尝试执行操作时,它们会出现。正如您在示例中看到的那样,通常推送页面两次或更多次没有问题,只要在第一次推送完成后开始第二次推送即可。

这里是您的 splitternavigator 的确切代码的演示。

所以错误不是来自您提供的代码,而是来自其他地方。

我唯一能想到的是,如果由于某种原因 popPage 方法未能正确完成,则会看到您提到的行为。也许如果您向我们提供您自己的代码笔,可以重现问题,我们可以进一步调试它。

虽然强烈推荐的替代方法是在您执行操作之前强制状态。然而,这并不能解决问题,而只是掩盖它。当然,与所有 hack 一样 - 它可能会在未来的版本中中断。

myNavigator._isRunning = false;

更新:

这是您在 cmets 中提供的两支更新后的钢笔: https://codepen.io/IliaSky/pen/YWOOkW?editors=1010 https://codepen.io/IliaSky/pen/QEVVGm?editors=1010

基本上,您在init 事件上添加处理程序,每当添加页面时都会触发该事件。因此,根据您的逻辑,您正在为每个页面添加越来越多的处理程序。只要确保只添加一次就可以了。

添加如下内容:

if (e.target.id == 'pagename') ...

或者干脆

$(document).on("init", '#dashboard_page', function(){ ... }

【讨论】:

  • 啊,这有帮助。似乎这是我的功能,每次我按下磁贴时,都会不断向pushPage() 添加越来越多的请求。我不知道为什么。而且我不认为它解释了我在使用load() 时看到的拆分器行为(我也会尝试在 CodePen 中复制它)。
  • 添加了拆分器的 CodePen。
  • 好的,我知道原因 - 我会尽快更新我的答案。基本上,您正在添加越来越多的事件处理程序,您添加的每个页面。所以只是你打电话给loadpushPage 的次数越来越多。 :)
  • 完成 - 随时查看更新中的代码笔。同样作为一般规则,您应该小心这些事情,不仅是温泉,还有任何 javascript 代码。这是一个常见问题,但在这些情况下稍加小心会大有帮助。
  • 成功了,但我不能说我非常了解正在发生的事情。听众是否以某种方式坚持不懈?我的想法是让每个页面都有监听器,因为每个页面都会有一个汉堡按钮(例如)。因此我省略了页面规范并让它在每个init 上运行。您是否碰巧知道任何可以解释这种行为的文章/书籍?不过感谢您的帮助!
【解决方案3】:

看看.one() from jQuery - 事件处理程序将只对每个元素执行一次以防止错误:未捕获(承诺中)pushPage 已经在运行

$(".tile_handler").one("click", ".imalink", function () {
var link = $(this).data().href;
if(link != null){
    document.querySelector("#myNavigator").pushPage(link, { animation: "slide-ios" });
}})

【讨论】:

    猜你喜欢
    • 2019-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多