如何使用Backbone.js在changePage之后显示主要的JQuery Mobile页面

时间:2013-11-21 17:26:44

标签: jquery jquery-mobile backbone.js

我正在开发一个使用RequireJS和BackboneJS的JQuery Mobile应用程序(1.4rc1)。应用程序并不复杂,但是太多了。我已经能够设置路由器,它正在正确调用路由方法。我的页面除了主页(位于index.html中),保存在名为`/ pages'的目录中。

应用程序加载正常并调用家庭路由器功能。我稍后会禁用该行为。 我点击登录链接,然后加载/pages/login-page.html将页面添加到DOM并显示它。

问题: 当我点击后退按钮时,调用home的路由器功能,然后调用$.mobile.changePage("#mainpage"),但不会重新显示主页,也不会显示任何错误。

我确保mainpage仍在DOM中,并且正在调用正确的路由器函数。

为什么即使我调用changePage,主页也不会重新显示? 日志:

before start mobileRouter.js:5
before home: http://localhost:8080/host/index.html mobileRouter.js:14
after home: http://localhost:8080/host/index.html#mainpage mobileRouter.js:16
after start mobileRouter.js:7
before login: http://localhost:8080/host/index.html#mainpage mobileRouter.js:19
after login: http://localhost:8080/host/index.html mobileRouter.js:21
before home: http://localhost:8080/host/pages/login-page.html mobileRouter.js:14
after home: http://localhost:8080/host/index.html#mainpage mobileRouter.js:16

相关代码:

mobileRouter.js

define(["jquery", "backbone"],
        function($, Backbone) {
            var Router = Backbone.Router.extend({
                initialize: function() {
                    console.log("before start");
                    Backbone.history.start();
                    console.log("after start");
                },
                routes: {
                    "": "mainPage",
                    "loginpage": "loginPage",
                },
                mainPage: function() {
                    console.log("before home: " + document.baseURI);
                    $.mobile.changePage("#mainpage");
                    console.log("after home: " + document.baseURI);
                },
                loginPage: function() {
                    console.log("before login: " + document.baseURI);
                    $.mobile.changePage("pages/login-page.html");
                    console.log("after login: " + document.baseURI);
                }
            });
            return Router;
        });

的index.html

<!doctype html>
<html class="no-js ui-mobile-rendering" lang="en">
    <head>
    <title>The Measure Of It</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="lib/dev/jquery.mobile.structure-1.4.0-rc.1.css">
    <link rel="stylesheet" href="lib/dev/jquery.mobile.theme-1.4.0-rc.1.css">
    <script src="require.js" data-main="mobile"></script>
    </head>
    <body>
    <div data-role="page" id="mainpage">
        <div data-role="header">
        <h1>Main Page</h1>
        </div><!-- /header -->

        <div data-role="content">

        <p><a href="#loginpage">Login</a></p>
        </div><!-- /content -->

        <div data-role="footer">
        <h4>Page Footer</h4>
        </div><!-- /footer -->
    </div>
    </body>
</html>

/pages/login-page.html

<!doctype html>
<html lang="en">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>page demo</title>
    </head>
    <body>
    <div data-role="page" id="loginpage">
        <div data-role="header">
        <h1>Login</h1>
        </div>
        <div data-role="content">
        <h2>email</h2>
        <h2>password</h2>
        </div>
        <div data-role="footer">
        <h1>Login Footer</h1>
        </div>
    </div>
    </body>
</html>

mobile.js

require.config({
    paths: {
        "jquery": "lib/dev/jquery-1.10.2",
        "jquerymobile": "lib/dev/jquery.mobile-1.4.0-rc.1",
        "underscore": "lib/dev/lodash",
        "backbone": "lib/dev/backbone",
        "routers": "app/routers",
    },
    shim: {
        "backbone": {
            "deps": ["underscore", "jquery"],
            "exports": "Backbone" 
        }
    }
});

require(["jquery", "backbone", "routers/mobileRouter"], function($, Backbone, Mobile) {
    $(document).on("mobileinit",
            function() {
                $.mobile.linkBindingEnabled = false;
                $.mobile.hashListeningEnabled = false;
            }
    );

    require(["jquerymobile"], function() {
        this.router = new Mobile();
    });
});

1 个答案:

答案 0 :(得分:4)

当篡改导航时,我遇到了同样的问题。这一切都归结为JQM没有找到DOM中的页面,尽管它在那里。您可以console.log通过导航小部件,您将看到JQM退出的位置以及原因。它通常可以从外部修复,因此无需破解JQM。

查看最新的JQM.js here

  1. 查找此行$.widget( "mobile.pagecontainer", {

  2. 然后找到change方法(相当远)。控制台登录:

            console.log("transition A")
            this._loadUrl( to, triggerData, settings );
        } else {
            console.log("transition B")
            this.transition( to, triggerData, settings );
        }
    
  3. 您应该在此处进行操作,接下来查看load方法,该方法从_loadUrl调用。 Load完成Ajax调用或转换,所以如果你没有得到它,你应该在这里找到原因。控制台content

        content = this._find( absUrl );
        console.log(content)
    
  4. 如果您的网页位于DOM中,则应将内容设置为您的网页。另外console就在下方:

        // If it isn't a reference to the first content and refers to missing
        // embedded content reject the deferred and return
        if ( content.length === 0 &&
            $.mobile.path.isEmbeddedPage(fileUrl) &&
            !$.mobile.path.isFirstPageUrl(fileUrl) ) {
            console.log("if you are here:")
            console.log("content is not found = "+ content.length === 0)
            console.log("it's NOT the first page = " + !$.mobile.path.isFirstPageUrl(fileUrl))
            console.log("it's an embedded page (i believe like a dialog, unlikely) = )"+$.mobile.path.isEmbeddedPage(fileUrl)) 
            deferred.reject( absUrl, settings );
            console.log("GOOD BYE")
            return;
        }
    
  5. 如果content为空,请检查_find方法,您应该在哪里找到解决方法。控制台充足并阅读JQM的评论!:

            var fileUrl = this._createFileUrl( absUrl ),
            dataUrl = this._createDataUrl( absUrl ),
            page, initialContent = this._getInitialContent();
    
            console.log("fileUrl ="+fileUrl)
            console.log("dataUrl ="+dataUrl)
    
            page = this.element
            .children( "[data-" + this._getNs() +"url='" + dataUrl + "']" );
            console.log(page)
    
  6. 您看到pagedata-url而不是id(!)决定。因此,一种解决方法是将正确的data-url添加到您的网页中。正确的意思是JQM所期望的,而不是正确的......另一个问题可能是dataUrl,所以检查一下这是什么,以及它是否是你要去的页面的网址。我设法通过将data-url设置为我需要的任何内容来解决一些问题,从而确保JQM将在DOM中找到该页面。继续...

        if ( page.length === 0 && dataUrl && !$.mobile.path.isPath( dataUrl ) ) {
            page = this.element.children( $.mobile.path.hashToSelector("#" + dataUrl) )
                .attr( "data-" + this._getNs() + "url", dataUrl )
                .jqmData( "url", dataUrl );
                console.log(page)
                console.log(!$.mobile.path.isPath( dataUrl ));
        }
    
  7. page的第二个音高,如果第一个音高不起作用。务必检查第3个参数。再试一次:

            if ( page.length === 0 &&
            $.mobile.path.isFirstPageUrl( fileUrl ) &&
            initialContent &&
            initialContent.parent().length ) {
            page = $( initialContent );
            console.log(page)
            console.log($.mobile.path.isFirstPageUrl( fileUrl ))
            console.log(initialContent)
            console.log(initialContent.parent().length)
        }
    
  8. 就是这样。除非您的错误是基本的......您应该在这里找到解决方案。让我知道你被困在哪里。我会尽力帮忙。

  9. 修改
    可能的解决方法:如果第一页JQM存储包含一个标签,它通常不会(因为你从index.html开始,你可以通过手动删除其中的主题标签JQM来解决这个问题。历史 - 仅限第一页。

    这只需要在向后转换时完成,因此您需要pagebeforechange的监听器,然后调用它:

    // capture only when toPage is an object
    if (typeof data.toPage !== "string") {
      // only when going back!
      if (e === undefined) {
        // only when going back to the first page
        if ($.mobile.navigate.history.initialDst &&
            window.location.hash !== "") {
    
          // clean url
          clean_url = window.location.href.split("#")[0];
          parsed_url = $.mobile.path.parseUrl(clean_url);
    
          // set in JQM
          $.mobile.navigate.history.stack[0].hash = "";
          $.mobile.navigate.history.stack[0].url = clean_url;
          $.mobile.path.documentUrl = parsed_url;
          $.mobile.path.documentBase = parsed_url;
        }
      }
    }
    

    适合我。您可能需要修改一下,但原则是remove the hash information on JQMs initial history entry