zoukankan      html  css  js  c++  java
  • 【新手向】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

  • 相关阅读:
    Android Studio 单刷《第一行代码》系列 05 —— Fragment 基础
    Android Studio 单刷《第一行代码》系列 04 —— Activity 相关
    Android Studio 单刷《第一行代码》系列 03 —— Activity 基础
    Android Studio 单刷《第一行代码》系列 02 —— 日志工具 LogCat
    Android Studio 单刷《第一行代码》系列 01 —— 第一战 HelloWorld
    IDEA 内网手动添加oracle,mysql等数据源,以及server returns invalid timezone错误配置
    eclipse maven设置
    IntelliJ IDE 常用配置
    eclipse maven 常见问题解决方案
    Maven 安装和配置
  • 原文地址:https://www.cnblogs.com/babysay123/p/4494568.html
Copyright © 2011-2022 走看看