• 【新手向】jQuery Mobile中动态加载或执行脚本的分析


    jQuery Mobile是我新的项目中要用到的移动端框架,之所以要使用它,仅仅是因为它的兼容性很好,页面之间的轮转及其优雅。但是jQuery Mobile的UI我并不喜欢,因此又引入bootstrap。在开发中发现,因为JQM采用ajax的方法加载链接到的页面,所以无法像我们之前的设计 一样,把不同页面的脚本放在head之间,即使将这些脚本转移到body之间,也可能造成一些代码无法执行。本文简单的提几个我自己开发中遇到的情况。

    1.框架的init初始事件

    使用jquery的习惯就是$(document).ready开头,然而这在jqm中行不通,因为ready事件只执行一次。当你打开一个URL 时,jqm拦截了jquery的ready事件,在ready之前要执行一大通,其中主要的是mobileinit事件。因此,如果对mobile的一些 核心配置,应该放在mobileinit事件钩子中。

    $(document).on('mobileinit',function(){
      $.mobile.pageLoadErrorMessage="加载出错了!"
    });
    但是有一个非常重要的点是,mobileinit之后DOM还没有加载完,因此如果你把对DOM的操作放在mobileinit事件钩子中的话,是没有用的,比如说append、remove等。

    ready事件发生在DOM刚刚加载完的时候,这个时候基本上各种操作都可以做了。如果你的移动端web用了jqm,你要记住,点击一个链接虽然 URL变化了,看到的页面也变化了,但是ready事件早都执行完毕了,所以不会再执行ready事件了,除非再刷新一下页面。如果你通过审查元素查看, 可以发现,加载的页面其实是将链接指向的页面的body内容抓取过来,放在一个div data-role=’page’中,把前面的一个页面隐藏起来。所以实际上很简单,如果你在ready中使用了on或者古老的live等函数来绑定新事 件,还是可以的,例如:

    $(document).ready(function(){
      $(document).on('click','.btn',function(){
         alert('ok');
      });
    });
    上面这段代码中因为使用了on来绑定click事件,所以通过ajax加载出来的页面中的.btn点击时也可以响应。但是有些插件要求在DOM加载时就执行的,那就没有办法了。JQM提供了新的事件来解决这个问题,即pageinit。

    pageinit发生在通过点击链接加载新页面的时候,因为整个应用都是通过ajax实现的加载,所以当一个新页面打开的时候,仅仅是一个DOM append和element hide的就可以实现的,要在一个新页面打开的时候执行某个动作怎办呢?靠pageinit。比如你现在有两个页面A、B,同时使用了一个幻灯插件,但是 幻灯插件只在ready事件中执行了,入口如果是A页面,你进入A时可以看到幻灯,但是点击进入B的时候发现幻灯没有加载。这个时候把幻灯的代码放到 pageinit事件钩子中。

    $(document).on('pageinit',function(){
      flash_set();
    });
    可是问题还是来了,有的时候即使你在pageinit事件钩子中使用代码也无法执行。你是否想起来mobileinit和ready的区别了,前者 在DOM加载完之前,后者在DOM刚刚加载完的时候。我们完全可以形象的把pageinit比作mobileinit,那么谁来顶替ready呢?jqm 提供了一个pageshow事件,pageshow则是发生在一个新的页面完全展现出来之后,这个时候不要说DOM了,基本上可以说是一个页面加载的最后 阶段,所以这个时候做什么事都可以,包括jqm通过ajax操作新加载进来的DOM。

    2.如何放置你的代码

    通过上面的解说你可能会觉得,全部放在pageshow里面不就好了么。但事实是没有必要每个页面都执行那么多脚本,而且你还要考虑如何把它们安排 在不同的页面位置。例如css,如果你打算直接在某一个页面中使用单独的css,那么不要用link放在head之间,因为如果它是被新加载进来 的,head之间的任何代码都不会被加载进来,你只能把这堆css放在页面的body中间。

    如果你的代码放置的不好,可能导致脚本执行混乱。例如你的HTML元素中在不同的页面使用相同的id,就可能因为ajax加载导致同一个DOM中出 现两个一样的id,导致执行混乱。即使你在新页面中使用了新的javscript代码,也有可能无法执行,例如你希望在新的页面中对提交的表单进行检查, 于是在新页面的body中间加入了下面的代码

    $('#form').submit(function(){
      ...
    });
    结果发现根本不执行,原因很简单,submit事件只有在ready的时候被加入事件监听的序列,而新加的js早就过了ready的时间了,因此,上面这段代码应该换为

    $(document).on('pageshow',function(){
    $('#form').submit(function(){
      ...
    });
    });
    3.页面跳转问题

    jqm遇到使用PHP header location做的页面跳转时,就傻了,什么也加载不出来。如果遇到你要页面跳转,我教几个办法,应对你应用中的跳转问题。

    第一种,使用data-ajax=”false”取消Ajax页面加载。虽然jqm的页面轮转看上去确实很酷,但在不得已的情况下,只能舍弃了。这 个时候你必须注意:如果重新执行页面DOM,你新的页面中引入的css、js等能否满足之后打算加载的页面,因为一旦你取消了Ajax,就相当于换了一个 入口页面,网页的标题变了,加载的文件也变了。

    第二种,通过PHP判断,在不同的情况下显示不同的链接。例如需要用户登录的页面,有些页面必须用户登录了才能看,可以用PHP判断,如果没哟登 录,那些内页的链接直接统一换成登录页的链接,如果已经登录,则正常显示。但这个地方要注意,比如首页,可能也有这样的链接,如果你登录了,首页DOM中 的链接是不会变的,所以你需要在登录操作之后刷新URL,或者通过Ajax的success回调函数中,修改这些链接。

    第三种,使用$.mobile.changePage实现间接跳转。jqm之所以不能实现跳转,是因为它的Ajax加载页面无法绕过header, 所以如果你最好不要有跳转,比如你需要跳转的地方,干脆直接引入跳转到的页面,把页面显示出来。但是这样明显是不大好的,所以实在没有办法的时候,使用这 里提出来的间接跳转。比如你打算某一个地方使用header location了,这个时候打住,把这个跳转代码换成下面的代码:

    <html>
    <head>
    <title>跳转页面...</title>
    <meta charset="utf-8">
    </head>
    <body>
    <script>
    $.mobile.changePage('{$url}');
    </script>
    </body>
    </html>

    $url就是要跳转到的目标地址。这个实现的原理很简单,Ajax加载的代码就是上面的<script>部分,激活了 changePage,于是开始跳转。不过这个动作实际上在用户体验上并不好,因为这个跳转会出现一个空白页,虽然不影响大局,而且还非常流畅的实现了跳 转,但是如果用户追求细节,可能就需要你对这个界面进行进一步的美化,例如加入一些跳转提示图片等。

    jquery mobile动态添加元素之后不能正确渲染

    listview: 添加 jq(".detail").listview("refresh");
    div或其他:添加.trigger( "create" );
    ======================================================================

    jqm在初始化页面时会根据data-xxx在各元素中插入jqm的属性和类等。在页面初始化结束后,如果动态的插入一个元素,往往显示很丑陋,因 为没有插入jqm的样式。这个可以用浏览器里的开发工具来查看,会发现有些元素多了很多类,而动态插入的元素代码还是你写的那样子。

    如果要使动态插入的元素具有jqm的样式,可以对jqm对象触发create事件:

    <span style="font-size:18px;"> $(selector).trigger('create');</span> 

    create事件适用范围广,甚至可以是 不存在的元素(raw markup?),比如要插入一个按钮

    $('<a data-role="button">dy button</a>').appendTo('#content').trigger('create');

    有些对象提供了refresh 方法,如listview、flip toggle。与create的区别是refresh方法需要作用在已存在的对象上,如

    $('ul').listview('refresh'),而且refresh只会去更新新加入的元素,如listview里最新append的元 素会更新,原有的保持不变。(不知有没理解错,有些没测试。原文http://stackoverflow.com/questions/7663078 /jquery-mobile-page-refresh-mechanism

    不使用jqm样式:

    如果不希望jqm自动初始化你的元素,有两种方法。加入data-role="none"属性,或者在mobileinit事件中对keepNative选项进行配置

    $(document).bind('mobileinit',function(){
     $.mobile.page.prototype.options.keepNative = "select, input.foo, textarea.bar";
    });

    材料源自:http://www.111cn.net/wy/jquery/71787.htm

  • 相关阅读:
    有向强连通分支Tarjan算法
    让理科生沉默,让文科生落泪的题
    迷宫求解(数据结构栈应用)
    编程中无穷大常量的设定技巧
    poj 3159 差分约束+spfa
    codevs 1690 线段树
    uvalive 2756 环形排列颠倒的次数
    poj 2182 树状数组
    uva 10943 数学
    uva 10780 分解质因数
  • 原文地址:https://www.cnblogs.com/babysay123/p/4494568.html
Copyright © 2020-2023  润新知