jQuery Mobile 脚本加载问题

刚开始使用jQuery Mobile,发现很多问题需要重新考虑,比如脚本加载问题。

在普通html中,如果a.html中有链接到b.html,b.html中有类似代码:

$(document).ready(function() {
alert("hello");
});

则这段代码可以被正常执行。

而在jQuery Mobile中,这样做就行不通了,在浏览器中直接刷新b.html,则代码可以正常执行,而从a.html跳转到b.html时则不会被执行!为什么?

参见:

http://www.cnblogs.com/pinocchioatbeijing/archive/2013/12/08/3463857.html

第一次做用jQuery Mobile做东西,发现一些跟平时的思维习惯不太一样的。其中这个框架的页面加载机制便是其中一个。如果不明白其中的奥秘,往往会出现一些让人摸不着头脑的怪现象,比如页面进入后点击按钮后Javascript就是不执行,而用F5刷新页面后又可以正常执行等。

即使我们明白了HTML文件与jQuery Mobile中page概念的区别,也还是不能解决上述问题。当然,了解这个是一个大前提。原来,jQuery Mobile是用Ajax的方式加载所有HTML中的标记data-role="page"的DIV元素中,第一个HTML页面一般都是完全加载,包括 HEAD BODY 都会被加载到DOM中,完成后便是链接到的其他页面内容的加载。 第二个HTML页面只有 BODY 中的内容会被以Ajax的方式加载到头一个HTML的 DOM中。 并且第二HTML页面的 BODY 中的内容也并非全部加载,而仅仅是其中的第一个带data-role="page"属性的DIV会被加载进去,其余的东西则无缘进入页面渲染。

直接上代码,或许更容易让人明白些:

index.html

<!DOCTYPE html>
    <html lang="en">
        <head>
            <!-- META TAGS Declaration -->
            <meta charset="UTF-8">
            <title>TEst</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0;" />
            <meta name="apple-mobile-web-app-capable" content="yes" />
            <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" />
            <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
            <script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>
            <script>
            $(document).on(‘pagebeforeshow‘, ‘#foo‘, function(){
                alert($(‘#body-test‘).html());
            });
            </script>
        </head>

        <body id="body-test">
            <div data-role="page" id="portfolio"  data-add-back-btn="true">
                <div data-role="content" data-theme=‘c‘ >
                    <a href="test.html" data-role="button">Go to Bar</a>
                </div>
            </div><!-- Page Project #1 -->
        </body>
</html>

test.html

<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="style/jquery.mobile-1.3.1.css" />
        <script src="jquery-js/jquery-1.10.1.js"></script>
        <script src="jquery-js/jquery.mobile-1.3.1.js"></script>
        <title>Foobar</title>
    </head>

    <body>
        <div data-role="page" id="foo">
            <div data-role="content">
                <a href="#bar" data-role="button">Go to Bar</a>
            </div>
        </div>

        <div data-role="page" id="bar">
            <div data-role="content">
                <p>Bar</p>
            </div>
        </div>
    </body>
</html>

好了,再看这篇文章:

http://stackoverflow.com/questions/17403825/link-fails-to-work-unless-refreshing/17403907

他还有另外一篇文章:

http://www.gajotres.net/how-jquery-mobile-page-handling-affects-javascript-executions/

How jQuery Mobile page handling affects javascript execution

For us to understand this situation we need to understand how jQuery Mobile works. It uses Ajax for page loading into the DOM.

First page is loaded normally. Its HEAD and BODY is loaded into the DOM. That content will stay there (unless page is refreshed) to await further content loading. When second page is loaded, only its BODY content is loaded into the DOM, and when I say its BODY content I mean DIV with an attribute data-role=”page” and its inner content.

This may not sound like something problematic, but you should think twice. What if we have several HTML pages and every and each page has something unique, let’s say different javascript intended to be used only during that page execution, not to mention additional CSS files. Everything found in a HEAD of those files are going to be discarded, and its javascript is not going to be executed.

Unfortunately, you are not going to find this described in their documentation. This is either thought to be a common knowledge or they just forgot to mention it.

There are several solutions to this problem; some are good and some are bad, everything should depend on a project architecture.

Intro

This article is an response to my Stackoveflow answer that can be found here.

Solution 1

In your second page and every other page, move your SCRIPT tag into the BODY content, like this:


1

2

3

4

5

6

7

8

<body>

    <div data-role="page">

        <script>

            // Your javascript will go here

        </script>

        // And rest of your HTML content

    <div>

</body>

This is a quick solution but an ugly one.

Working example can be found in my other answer here: Pageshow not triggered after changepage

Another working example: Page loaded differently with jQuery-mobile transition

Solution 2

Move all of your javascript into the original first HTML. Collect everything and put it into a single js file, into a HEAD. Initialize it after jQuery Mobile has been loaded.


1

2

3

4

5

6

<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>

At the end of this article, I will describe why this is a good solution.

Solution 3

Use rel=”external” in your buttons and every elements you are using to change page. Because of it, Ajax is not going to be used for page loading and your jQuery Mobile app will behave like a regular web application. Unfortunately, this is not that good solution. If Ajax is not used for page loading, you will loose a lot of functionalities that make jQuery Mobile such a great framework.


1

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

Official documentation, look for a chapter: Linking without Ajax.

Realistic solution

Realistic solution would use solution 2. But unlike solution 2, I would use that same index.js file and initialize it inside a HEAD of every possible other page.

Now, you may ask WHY is that?

jQuery Mobile is buggy, and sooner or later there’s going to be an error and your app will fail (including loaded DOM) if your js content is inside a single HTML file. DOM could be erased, and browser or you will refresh your current page. If that current HTML page don’t have javascript initialized inside its HEAD then that web app will not work until everything is restarted.

In the end, when creating a jQuery Mobile application spend some time thinking about a page architecture. If you need a help take a look at my other articlewhere I am discussing secrets of a good jQuery Mobile architecture.

好吧,最后总结一下:

如果多个html,请将第二个页面的脚本放在第一个page后面,紧跟在page后面,像这样:

<body>

<div data-role="page">

    <script type="text/javascript">

        $.support.cors =true;
        $.mobile.allowCrossDomainPages=true;

        $(document).ready(function() {
            alert("hello");
        });

    </script>
    <div data-role="header" data-position="fixed">

.......
时间: 2024-10-26 05:33:18

jQuery Mobile 脚本加载问题的相关文章

jQuery Mobile页面加载机制及页面跳转出现的问题

实习也半个多月了,断断续续做了一些事情,虽然一开始有一些不开心,但是随着慢慢的了解感觉自己也是在慢慢的成长,也在慢慢的学习,很开心也很满足,希望可以一直这样下去. 今天遇到了一个问题,主要就是我们公司首页的一个图片轮播的效果有一些问题:就是进入主页的时候,图片轮播正常,但是当我进入到其他页面的时候,点击其中的home按钮回到主页面的时候,图片的轮播功能就不行了,由于我们的系统使用jQuery Mobile做的,而且这个东西我也就接触才半个月(当初进公司的时候才学的),所以很多东西都不知道,也不了

jquery mobile 动态加载标签时,无法正常展示样式

原因 在chrome中审查元素,发现其增加了很多没有直接写在页面上的标签和样式.页面标签首先经过jquery.mobile-1.4.5.min.js的处理,添加了许多标签,然后再用css布局 解决方案 1.将jquery.mobile-1.4.5.min.js处理后的样式动态添加,即将chrome中审查元素得到的完整元素及样式复制下来,动态添加 缺点:代码很多,而且加了很多奇怪样式和各种标签 2.refresh 各类标签的刷新 1.Textarea fields $('body').prepen

关于Jquery,js脚本加载执行先后顺序的一些事

好久没用Jquery了,最近有个东西需要写一下,就想了想那些让脚本延缓执行的一些方法有什么区别呢. (1)当然,第一种方式就是将脚本内嵌在html中相应需要执行的地方,需要等到页面加载完成的话就放在最后.当然这已经是大家很不屑的做法,一般也就是一些测试啊什么的时候会用用或者代码就一几句话,其他很少会这么做了.作为外部文件引入的优点也就不赘述了,一般都明白. (2)将<Script>标签从head放到〈/body〉之前,其他html内容之后.这也很好理解,主要的html加载完之后,脚本才开始运行

浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及其他的细节问题.而除了defer和async特性,动态脚本和Ajax脚本注入也是两种常用的创建无阻塞脚本的方法.总的来看,这两种方法都能达到脚本加载不影响页面解析和渲染的作用,但是在不同的浏览器中,这两种技术所创建的脚本的执行时机还是有一定差异,今天我们再来探讨一下通过动态脚本技术和Ajax注入的脚本在这些方

JavaScript之jQuery-4 jQuery事件(页面加载后执行、事件处理、事件冒泡、事件对象、模拟操作)

一.jQuery 页面加载后执行 代码执行的时机选择 - $(document).ready()方法和 window.onload事件具有相似的功能,但是在执行时机方面是有区别的 - window.onload 事件是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行 - $(document).ready()方法注册的事件处理程序,在DOM完全加载后就可以调用 - 一般来讲, $(document).ready()的执行要优于window.onload事件 - 需要注意的是,

JavaScript异步编程(二) 异步的脚本加载

异步的脚本加载 问题: <head>标签里的大脚本会滞压所有页面渲染工作,使页面在脚本加载完毕前一直处于白屏: <body>标签末尾的大脚本使用户只能看到静态页面,原本应进行渲染的地方却是空的: 解决方案: 对脚本分而治之; 负责让页面更好看.更好用的脚本立即加载,可稍后再加载的脚本稍后再加载. HTML5的async/defer属性 ?<script标签> 经典型和非阻塞型 理想情况下,脚本的加载应该与文档的加载同时进行,并且不影响DOM的渲染. 这样,一旦文档就绪就

jQuery实现DOM加载方法源码分析

传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... }  但是onload事件触发过于缓慢,尤其是在存在很多外部图片或者视频文件的时候,为了更好的了解这一点有必要知道一个html文档是如何进行加载的,这里引用一个园友的表述: 1.用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件: 2.浏览器开始载入htm

你不知道的JavaScript--Item26 异步的脚本加载

先来看这行代码: <script src = "allMyClientSideCode.js"></script> 这有点儿--不怎么样."这该放在哪儿?"开发人员会奇怪,"靠上点,放到<head>标签里?还是靠下点,放到<body>标签里?"这两种做法都会让富脚本站点的下场很凄惨.<head>标签里的大脚本会滞压所有页面渲染工作,使得用户在脚本加载完毕之前一直处于"白屏死机&

也说JS脚本加载控制

问题背景 前端采用的 iframe + html 做后台管理系统.现在js.jquery插件非常多,每次页面都是引用就类似这样: <script src="../Scripts/jquery-1.7.1.js"></script> <script src="../Scripts/uploadify/jquery.uploadify.js"></script> <script src="../Script