jQuery Mobile动态刷新加载的页面

10

我有一个名为index.html的page1,它是一个包含头部和脚本等的自包含网站。在这个页面上有一个按钮,当点击它时,会通过ajax加载page2并将page2插入到page1中。Page2只是带有数据角色="page"和其中的HTML的div,它不是一个自包含的页面。但是,URL会更改为page2.html,如果我“刷新”页面,它不会加载完整的页面,因为page2不是完整的页面,它只是要被注入到page1中。

我尝试设置data-url="index.html&dashboard"(仪表板是page2上的主ID),在这种情况下,URL看起来正确,因为它仍然是index.html&dashboard,所以即使您在page2上,页面刷新也会重新加载page1。但现在,jquery出问题了,并且永远停留在加载屏幕上,因为它找不到“dashboard”,因为该内容仅在用户单击按钮后添加。

我该如何解决这个问题?

谢谢。

page1 index.html

<!DOCTYPE HTML>
<html>
<head>
<title>title</title>
<script><script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jquery.mobile.js"></script>
<script type="text/javascript" charset="utf-8" src="js/global.js"></script>
<script type="text/javascript" charset="utf-8" src="js/login.js"></script>

<link rel="stylesheet" type="text/css" href="css/jquery.mobile.css" />
<link rel="stylesheet" type="text/css" href="css/style.css" />

<script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jquery.mobile.js"></script>
<script type="text/javascript" charset="utf-8" src="js/login.js"></script>

<link rel="stylesheet" type="text/css" href="css/jquery.mobile.css" />
<link rel="stylesheet" type="text/css" href="css/style.css" />

</head>
<body>
    <div data-role="page" data-theme="b">

        <div data-role="header" data-theme="b">
            <h1>Login</h1>
        </div>
        <!-- /header -->

        <div data-role="content">
            <div class="row">
                <label for="login_name">Login Name:</label> <input
                    class="ui-input-text" type="text" name="login_name" id="login_name" />
            </div>
            <div class="row">
                <label for="basic">Password:</label> <input class="ui-input-text"
                    type="password" name="password" id="password" />
            </div>
            <div class="row">
                <input type="checkbox" name="remember" id="remember" class="custom"
                    data-mini="true" /> <label for="remember">Remember Me</label>
            </div>
            <div class="row">
                <input type="submit" id="submit" name="submit" value="Submit" />
            </div>
        </div>
        <!-- /content -->

    </div>
    <!-- /page -->
</body>
</html>

页面2 仪表板.html

<div id="dashboard" data-role="page" data-theme="b" data-url="index.html&dashboard">

<div data-role="header" data-theme="b">
    <h1 id="page_title">Dashboard</h1>
</div>

login.js

$(function() {


$("#submit").click(function() {

    if ($("#login_name").val() == "") {
        alert("Please enter a login name");
        return false;
    }

    if ($("#password").val() == "") {
        alert("Please enter a password");
        return false;
    }

    $.post(URL + 'login', {
        'APIKEY' : APIKEY,
        'login' : $("#login_name").val(),
        'password' : $("#password").val()
    }, function(data) {
        if (data.error == "") {

            $.mobile.changePage("dashboard.html", { transition : "slide" });
        } else {
            alert(data.error);
        }

    }, "json");

});

});


Danny,jQuery Mobile网站上有几个教程和演示可以展示你所描述的确切功能,不是吗?如果你正在做与那些演示不同的事情,那么为什么不尝试发布你已经尝试过的代码,这样我们就有了可用的东西来工作。现在,你要求我们承担无用的负担,即使对于最强大、最有知识的人来说也很困难。 - jamesmortensen
好多了。谢谢。你能展示一下JS代码吗?请确保所有的代码都缩进了4个空格,否则它无法正确格式化。 - jamesmortensen
代码已经更新,谢谢。我的所有代码都能正常执行和工作,所以这不是代码无法工作的问题,而更多的是它如何工作的逻辑问题。 - Danny
丹尼,我已经提供了长答案,但是想到短答案可能已经足够了。此外,请查看jQuery移动站点上的示例。最好的方法是查看每个页面的源代码,这样您就可以看到内部发生了什么。祝你好运! - jamesmortensen
1个回答

7

简短回答

简短回答是,jQuery Mobile 希望您使用哈希来表示单个页面的状态:

  • /index.html - 页面 1
  • /index.html#dashboard - 仪表板。

相反,您正在加载一个全新的页面,而您应该只调用 JavaScript 来动态更改第一页的内容以代表第二页。

如果简短回答有意义,那太好了!如果没有,长回答非常详细,描述了两种解决此问题的方法。

长回答

您实际上正在问如何构建多页面移动网站,并使两个页面都可以通过标识资源的 URI 访问。

有两种方法可以解决这个问题。

多页面模板:

对于 jQuery Mobile,可以使用 jQuery Mobile 多页面模板 来实现。

一般的想法是,您的两个页面都在同一个 HTML 文档中,像这样:

<head>

</head>

<!-- This is your FIRST page -->
<div data-role="page" id="one">

    <div data-role="header">
        <h1>Multi-page</h1>
    </div><!-- /header -->

    <div data-role="content" >  
        <h2>One</h2>

        <p>I have an id of "one" on my page container. I'm first in the source order so I'm shown when the page loads.</p>  

        <h3>Show internal pages:</h3>
        <p><a href="#two" data-role="button">Show page "two"</a></p>    
        <p><a href="#popup"data-role="button" data-rel="dialog" data-transition="pop">Show page "popup" (as a dialog)</a></p>
    </div><!-- /content -->

    <div data-role="footer" data-theme="d">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page one -->

<!-- This is your SECOND page -->
<!-- Start of second page: #two -->
<div data-role="page" id="two" data-theme="a">

    <div data-role="header">
        <h1>Two</h1>
    </div><!-- /header -->

    <div data-role="content" data-theme="a">    
        <h2>Two</h2>
        <p>I have an id of "two" on my page container. I'm the second page container in this multi-page template.</p>   
        <p>Notice that the theme is different for this page because we've added a few <code>data-theme</code> swatch assigments here to show off how flexible it is. You can add any content or widget to these pages, but we're keeping these simple.</p>  
        <p><a href="#one" data-direction="reverse" data-role="button" data-theme="b">Back to page "one"</a></p> 

    </div><!-- /content -->

    <div data-role="footer">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page two -->

</body>

接下来,jQuery Mobile 的本质是使用 CSS 隐藏 id="two" 的 DIV 元素,并仅显示 id="one" 的 div。当用户单击带有 `href="#two"` 的超链接时,有一个监听器拦截 hashChange 事件并触发一些 JavaScript 代码,隐藏 id="one" 的 DIV 并显示 id="two" 的 DIV。
这使页面转换看起来非常流畅和快速,无需访问服务器以获取 HTML 标记。
动态注入内容:
如果您的数据更加动态,则另一种选择是使用 jQuery Mobile Dynamic Page Injection。该过程的一般前提与多页模板类似,即浏览器侦听 hashChange 事件,除了更改页面外,它还会向服务器发出 AJAX 请求以检索 JSON 内容。
<div id="home" data-role="page">
  <div data-role="header"><h1>Categories</h1></div>
  <div data-role="content">
    <h2>Select a Category Below:</h2>
    <ul data-role="listview" data-inset="true">
        <li><a href="#category-items?category=animals">Animals</a></li>
        <li><a href="#category-items?category=colors">Colors</a></li>
        <li><a href="#category-items?category=vehicles">Vehicles</a></li>
    </ul>
  </div>

</div>

当点击类别“动物”时,id="home"的DIV将被隐藏。在这个例子中,HTML不会重新加载,而是动态生成并填充JSON对象的结果。
以下是处理显示正确内容的代码:
// Load the data for a specific category, based on
// the URL passed in. Generate markup for the items in the
// category, inject it into an embedded page, and then make
// that page the current active page.
function showCategory( urlObj, options )
{
    var categoryName = urlObj.hash.replace( /.*category=/, "" ),

        // Get the object that represents the category we
        // are interested in. Note, that at this point we could
        // instead fire off an ajax request to fetch the data, but
        // for the purposes of this sample, it's already in memory.
        category = categoryData[ categoryName ],

        // The pages we use to display our content are already in
        // the DOM. The id of the page we are going to write our
        // content into is specified in the hash before the '?'.
        pageSelector = urlObj.hash.replace( /\?.*$/, "" );

    if ( category ) {
        // Get the page we are going to dump our content into.
        var $page = $( pageSelector ),

            // Get the header for the page.
            $header = $page.children( ":jqmData(role=header)" ),

            // Get the content area element for the page.
            $content = $page.children( ":jqmData(role=content)" ),

            // The markup we are going to inject into the content
            // area of the page.
            markup = "<p>" + category.description + "</p><ul data-role='listview' data-inset='true'>",

            // The array of items for this category.
            cItems = category.items,

            // The number of items in the category.
            numItems = cItems.length;

        // Generate a list item for each item in the category
        // and add it to our markup.
        for ( var i = 0; i < numItems; i++ ) {
            markup += "<li>" + cItems[i].name + "</li>";
        }
        markup += "</ul>";

        // Find the h1 element in our header and inject the name of
        // the category into it.
        $header.find( "h1" ).html( category.name );

        // Inject the category items markup into the content element.
        $content.html( markup );

        // Pages are lazily enhanced. We call page() on the page
        // element to make sure it is always enhanced before we
        // attempt to enhance the listview markup we just injected.
        // Subsequent calls to page() are ignored since a page/widget
        // can only be enhanced once.
        $page.page();

        // Enhance the listview we just injected.
        $content.find( ":jqmData(role=listview)" ).listview();

        // We don't want the data-url of the page we just modified
        // to be the url that shows up in the browser's location field,
        // so set the dataUrl option to the URL for the category
        // we just loaded.
        options.dataUrl = urlObj.href;

        // Now call changePage() and tell it to switch to
        // the page we just modified.
        $.mobile.changePage( $page, options );
    }
}

请注意,当查看类别页面和动物页面的URL时,可以看到HTML文档每次都是相同的。不同之处在于哈希值。

http://jquerymobile.com/demos/1.1.0/docs/pages/dynamic-samples/sample-reuse-page.html

http://jquerymobile.com/demos/1.1.0/docs/pages/dynamic-samples/sample-reuse-page.html#category-items?category=animals

当页面加载时,哈希值用于表示页面的状态。由于浏览器大多是无状态的,哈希是我们可以利用的一种技巧,以帮助确定应向用户显示哪个页面状态。
只需将您的changePage方法调用与类别页面菜单中使用的URL进行比较即可。
<li><a href="#category-items?category=animals">Animals</a></li>
<li><a href="#category-items?category=colors">Colors</a></li>
<li><a href="#category-items?category=vehicles">Vehicles</a></li>

请注意,当用户单击链接时,唯一变化的是哈希值,页面永远不会重新加载。但在您的示例中,实际上正在加载一个全新的页面:
// this is a new page, not a hash
$.mobile.changePage("dashboard.html", { transition : "slide" });

逻辑上讲,您需要重新考虑如何表示您的页面的策略。为了充分利用jQuery Mobile,请将您的第一个HTML页面视为所有CSS、JavaScript和静态内容的框架。
之后,您请求的任何资源都应该由具有相同页面后跟哈希值的URL来标识。
例如,如果您的静态页面是“index.html”,那么您的仪表板可能是“index.html#dashboard”。您还可以在id="dashboard" DIV中包含仪表板HTML,并动态地从服务器填充数据,或者通过AJAX加载HTML和数据。
第二点是,任何直接访问您的仪表板的人都需要访问“/index.html#dashboard”,这将加载您的原始页面,触发一些JavaScript来检查哈希,识别它包含“dashboard”,然后通过拉回动态数据来转换到仪表板页面。
有关更多信息,请参见jQuery Page Dynamic Documentation

谢谢,我会再仔细看看这个方法是否适用于我。实际上,我的例子相当简单,实际上将会有大约20个不同的页面,每个页面都有一组自定义JavaScript,并且每个页面都涉及到很多功能。 - Danny
我可能需要单独调用每个页面并忘记页面转换,我只喜欢页面之间的幻灯片效果,所以我会先尝试像上面那样的东西,但即使这样工作了,我还需要想办法根据加载的页面动态添加/删除和执行javascript文件,因为它将太大而无法在同一个dom中堆叠所有内容(并预加载所有js文件)。现在,如果他们有一种方法可以在完全不同的页面上进行页面转换,那就解决了一切,我只需使每个页面自包含。我会再做些研究:)谢谢。 - Danny
那么你最好使用第二种方法。创建一个单页模板,每次请求另一页时,只需用动态数据替换页面模板中的主DIV。将JS视为预加载函数库。 - jamesmortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接