为什么在jQuery Mobile中我必须把所有脚本放到index.html文件中?

26

在我的phonegap+jquerymobile项目中,我使用$.mobile.changepage进行重定向。然而让我困惑的是,我需要把所有页面的脚本都放到同一个index.html文件中。如果不这样做,重定向页面将无法执行其头部中的函数。

例如,我的index.html似乎是这样的:$(document).bind("deviceready",function(){$.mobile.changepage("test.html");})

接着,我的设备会重定向到test.html,它看起来像是:

$("#btnTest").click(function(){alert("123");})
<button id="btnTest">Test</button>
然而,脚本将永远不会在test.html中执行。然后我将脚本放到index.html中,我期望的结果得以实现。无论如何,如果我把所有的脚本都放到同一个页面上,项目将变得越来越难以维护。感谢您的帮助。
3个回答

60

简介

本文也可以在我的博客这里找到。

jQuery Mobile如何处理页面变化

要理解这种情况,您需要了解jQuery Mobile的工作原理。它使用ajax加载其他页面。

第一页正常加载。它的HEADBODY被加载到DOM中,等待其他内容。当加载第二个页面时,仅其BODY内容被加载到DOM中。更准确地说,即使BODY并没有完全加载。只有带有属性data-role="page"的第一个div将被加载,其他所有内容都将被丢弃。即使在BODY中有更多的页面,也只会加载第一个页面。此规则仅适用于后续页面,如果在初始HTML中有更多页面,则所有这些页面都将被加载。

这就是为什么您的按钮能够成功显示,但单击事件无法正常工作的原因。相同的单击事件,其父级HEAD在页面切换期间被忽略了。

这是官方文档:http://jquerymobile.com/demos/1.2.0/docs/pages/page-links.html

不幸的是,您不会在他们的文档中找到这个描述。他们可能认为这是常识,或者他们忘记描述这一点,就像我的其他主题一样。(jQuery Mobile文档很大,但缺少很多东西。)

解决方案1

在第二个页面和每个其他页面中,将您的SCRIPT标签移动到BODY内容中,如下所示:

<body>
    <div data-role="page">
        // And rest of your HTML content
        <script>
            // Your javascript will go here
        </script>
    </div>
</body>

这是一个快速解决方案,但还是有些丑陋。

可以在我的另一个回答中找到实际工作示例:changepage 后 pageshow 未触发

另一个有效的示例:使用 jQuery Mobile 过渡加载页面的不同方式

解决方案2

将所有 JavaScript 移动到原始的第一个 HTML 中。收集所有内容并将其放入单个 JS 文件中,放入HEAD中。在 jQuery Mobile 已加载后初始化它。

<head>
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no; target-densityDpi=device-dpi"/>
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
    <script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>    
    <script src="index.js"></script> // Put your code into a new file
</head>

最后我会解释为什么这是一个好的解决方案的一部分。

解决方案3

在你的按钮和每个用于页面跳转的元素中使用rel="external"。因为这样就不会使用ajax进行页面加载,你的jQuery Mobile应用程序将表现得像一个普通的Web应用程序。不幸的是,在你的情况下这不是一个好的解决方案。Phonegap 绝不能像一个普通的Web应用程序一样工作。

<a href="#second" class="ui-btn-right" rel="external">Next</a>

官方文档,请查找章节:无需使用Ajax进行链接

现实解决方案

现实解决方案将使用解决方案2。但不同于方案2,我会使用同一个index.js文件,并将其初始化到每个可能的其他页面的HEAD中。

现在你可以问我为什么

Phonegap和jQuery Mobile一样存在漏洞,迟早会出现错误,如果所有js内容都包含在一个HTML文件中,则您的应用程序将失败(包括已加载的DOM)。DOM可能会被删除,Phonegap将重新加载您当前的页面。如果该页面没有javascript,它将不起作用,直到重新启动。

最后的话

可以通过良好的页面架构轻松解决此问题。如果有人感兴趣,我写了一篇有关良好的jQuery Mobile页面架构的文章。简而言之,我讨论了在成功创建您的第一个应用程序之前,了解jQuery Mobile工作原理的知识是您需要知道的最重要的事情。


非常完美的答案!因此,我们的结论是不能将每个js文件分别放在每个页面中?这使得我们的应用程序真的很难维护。我担心这意味着一个Javascript错误会使整个JqueryMobile应用程序崩溃。 - Jack He
在方案1中,包含一个外部脚本文件是如此丑陋吗? - ogborstad
这绝对不是一个坏主意,我更喜欢将所有内容放在外部文件中。 - Gajotres
@Gajotres,方案1有什么不好的地方吗? - Anwar Chandra
脚本标签一直都是作为 HEAD 的一部分,但事件绑定强制它被用在 BODY 内。现在应该已经过去了,因为有委托事件的存在,但由于某些原因,人们仍然坚持旧的方式。基本上,唯一丑陋的东西就是这种解决方案的美学价值。 - Gajotres
1
天啊,如果我先读了这个,我就可以避免掉头发了,谢谢啊! - Cesar Bielich

1
与普通的HTML页面不同,jQuery Mobile在页面之间导航时使用ajax技术。因此,请确保在所有HTML页面中导入所有JS文件和库。
如果您仔细观察,您会发现加载第二个页面时会考虑来自上一个页面的JS文件。但是,如果您强制刷新当前页面,则当前页面的js文件将生效。
所以,正如我之前所说,请确保在所有html文件中导入js文件。
此外,无需调用deviceready,请使用以下语法调用特定于您的页面的js函数。
$(document).on('pageshow', '#YourPageID', function(){
    // Your code goes here
});

1
Jquery Mobile 使用 ajax 加载“页面”。这里的“页面”是一个带有 data-role=page 的 div。如果您加载一个物理页面 index.html,可以使用 changePage 导航到该页面内的任何“页面”div。
然而,如果您想从其他物理页面加载“页面”,jQM 只会加载该页面中的第一个“页面”div。实际发生的是,您没有更改页面,jQM 只是使用 ajax 加载特定的“页面”div 并将其注入到当前页面中。
您有两种可能的架构方式,其中一种是将所有“页面”放在一个 html 页面中并从那里导航。或者您可以使用多个页面架构。您总是可以混合使用这些方法。
要物理更改页面,您需要在链接中添加 rel=external。

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