如何在页面数据准备好之前延迟jQuery Mobile中的页面转换?

Mor*_*ner 20 javascript jquery-mobile knockout.js

我有一个使用jquery-mobile(jqm)和knockout构建的移动单页Web应用程序.应用程序本身有多个页面,但它们都包含在一个HTML文档中.

问题:在将"创建页面视图模型"从同步更改为异步行为后,我遇到了jquery-mobile在数据准备好之前触发其事件的问题.

背景:直到最近,我一直在处理样本数据,基本上是一个巨大的JSON blob,一切都很顺利.使用来自各种来源的视图模型的新异步组合,数据不会立即就绪,我的"buildViewModel"方法采用连续回调而不是仅仅同步返回数据.

我正在订阅pag​​ebeforecreate和pagebeforechange事件,并在此处触发代码以填充viewmodel.问题是从事件处理程序返回后,jqm在数据可用之前触发剩余的事件链.这导致页面转换到未准备的页面,这是不希望的.

我试图event.preventDefault在所有事件之前调用并在页面准备好a)增强后手动调用$ .mobile.changePage并且b)页面转换发生,但没有任何运气.

我已经扫描了jquery-mobile源,但是看不到任何看起来像是允许我延迟pagebeforeshow事件的东西,这本质上是我需要的才能正确渲染页面.

在jquery-mobile尝试增强页面之前和执行转换到页面之前,我如何确保1)数据可用并且2)已应用knockout来执行初始DOM操作?

我还考虑使用同步ajax来获取资源,但这(我认为)不适用于从设备加载的资源(使用PhoneGap/Cordova),并且还有其他我想避免的负面后果.

FWIW,我想通过在任何地方连接点击处理程序来避免手动处理所有导航事件,但如果需要,我会对所有解决方案持开放态度.

如果这是重复的,请道歉; 我搜索并阅读了大量问题,但没有找到完全相同的答案或问题.听起来不可思议的是我会成为第一个遇到这个问题的人,因为我认为这是一个常见的场景.

更新:澄清问题场景描述.

小智 13

我有同样的问题.

我能够想出的唯一解决方案是编写一个自定义转换处理程序,该处理程序推迟启动转换,直到Ajax请求完成.

这是一个显示技术的小提琴.小提琴不使用Knockout,但确实展示了如何推迟过渡.

基本上,因为$.ajax()返回一个promise,我可以将它传递给默认转换处理程序返回的promise,并从我的新处理程序返回它.

在我的pagebeforeshow处理程序中,我将Ajax保证附加到页面,以便转换处理程序可以访问它.不确定这是否是最佳方式,但我比使用全局变量更喜欢它.

我唯一不喜欢的是它延迟了转换的开始,直到Ajax响应到来,所以它可能感觉页面已经"挂起"给用户再次点击它们.手动显示加载消息会使其感觉更敏感.

希望这有帮助,如果您找到更好的解决方案,请告诉我!


Rom*_*ain 5

在面向jQuery Mobile中的动态内容时,延迟转换到新页面直到其内容就绪是一个非常常见的问题.解决这个问题最方便的方法是:

  • 而不是传统的href类型导航,将链接基于"点击"操作,这些操作将首先检索内容,在DOM中构建新页面,然后启动到此新页面的转换$.mobile.changePage.这种方法的优点是易于安装,缺点是您不使用经典href链接进行导航

  • pagebeforechange在文档级别绑定事件以检测在导航时目标页面是否应包含动态内容的页面之一.在这种情况下,您可以阻止默认导航发生,花时间生成页面,并在成功时进行转换.这在动态注入内容的JQM文档中有所描述.优点是您仍然可以依赖标准href链接导航,但它需要更多的代码和上游设计才能正确检测导航到页面并对其进行操作.

    $(document).on( "pagebeforechange", function( e, data ) {
        if ( typeof data.toPage === "string" ) {
             if ( data.toPage === "myDynamicPageName" ) {
                 e.preventDefault(); //used to stop transition to the page (for now)
    
                 /*
                    Here you can make your ajax call
                    In you callback, once you have generated the page you can call
                    $.mobile.changePage
                    (you can pass the Div of the new page instead of its name as
                    the changepage parameter to avoid interrupting again the page change) 
                 */
              }
          }
    });
    
    Run Code Online (Sandbox Code Playgroud)