深入jQuery Mobile


jQueryMobile上手非常容易,但是要做到近似于原生APP的效果则很不容易。 以下内容不断更新中,均为实际开发中的经验

追信魔盒PhoneGap打包模式下的最佳模式


追信魔盒的PhoneGap打包模式,将所有HTML文件、CSS文件和JS文件打包在客户端中,这样就不考虑在线模式的网络延迟问题,可以用各种方式将应用的表现更贴近原生程序

  • 采用OPOA(One Page, One Application)模式,将所有主要内容放置在一张页面中,这样可以确保不同的Page切换最为顺畅。
  • 尽可能将所有的点击链接通过javascript来控制。绑定jQueryMobile的tap事件来处理。这样可以确保最快响应点击事件
  • 使用$(document).bind('pageinit'),而不是 $(document).ready()。
  • 对不同的Page中的JS脚本分别实现载入后运行(默认的教程都是教你使用$(document).bind('pageinit')。例如:
$("#Home").live('pageinit',function() {
	//在这里执行#Home页面加载后需要运行的方法
});



  • 尽可能避免在转场时使用fade,这个方法在很多场合容易闪屏,使用slide相对保险一些。
  • 避免使用alert来弹出提醒,可以考虑使用PhoneGap的通知事件来实现纯原生客户端的提醒样式

固定顶部导航栏以及可能引发的问题

对于顶部导航栏,我们通常使用data-position="fixed"来固定顶部的显示。

如图,顶部固定的代码:



<div data-role="header" data-position="fixed">
    	<a href="#Home" data-icon="back" data-direction="reverse" data-transition="slide" >返回</a>
      <h1>
        复合大城
      </h1>
      <a href="#Home" data-icon="home" data-iconpos="notext" data-direction="reverse" data-transition="slide" class="ui-btn-right">首页</a>
      <div class="segmented-control ui-bar-d">
      	<div data-role="controlgroup" data-type="horizontal" id="fhdcList">
		<a href="#"  class="ui-btn-active" data-role="button">非凡血统</a>
	 	<a href="#" data-role="button" >完美规划</a>
		<a href="#" data-role="button" >大城崛起</a>
		<a href="#" data-role="button" >商学院</a>
	</div>
      </div>
    </div>



这样的效果在表现上已接近原生效果。

但是如果在真机打包模式下(并且所有Page放在一个Html文件中),会发现如果前后两张页面都采用了固定头部,在Slide过场效果下,第一次切换会先只显示下一张Page的头部覆盖当前Page,再切换到下一张,而并非第二张Page完整显示。 为了避免这种情况,可以将第一张Page的头部的fix属性去掉。对于一般的软件,如果只有两层内容深度,那么只要首页的顶部不固定即可。(对于此问题尝试增加DOM缓存等都无效,仅测试出这个解决方案)

点击链接响应速度慢的问题

对于a标记的点击导航,默认是在onclick事件中处理的。而移动客户端对onclick的响应相比PC浏览器有着明显的几百毫秒延迟。

在移动浏览器中对触摸事件的响应顺序应当是: ontouchstart -> ontouchmove -> ontouchend -> onclick

因此,如果确实要加快对点击事件的响应,就应当绑定ontouchend事件。

如果不用jQueryMobile,可以考虑用第三方的脚本,例如 http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone 。而那个地址中的代码不支持Android,可以考虑采用评论中的代码。这个脚本主要考虑到ontouchstart和ontouchend的触摸点位移,确保不会在用户滑动(swipe)画面后触发到点击事件。

对于使用jQueryMobile的人来说就幸运很多了,使用内置的tap事件即可在ontouchend事件环节捕获到被点击的请求,这个方法的响应时间明显快于onclick事件。代码范例如下:



$("#fhdclink").live('tap',function(event) {
	$.mobile.changePage($("#fhdc"), {
		transition: 'slide',
		reverse: false
	} );
	return false;
});



对载入文字和错误文字的汉化



$(document).bind("mobileinit",function() {
	$.mobile.loadingMessage = '页面载入中';
	$.mobile.pageLoadErrorMessage = '页面载入失败';
});



整合PhoneGap(Cordova)



<script data-minified="true" src="js/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="js/cordova.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).bind("mobileinit",function() {
	$.support.cors = true;
	$.mobile.allowCrossDomainPages=true;
});
  document.addEventListener("deviceready", onDeviceReady, false);
 
  function onDeviceReady() {
        // Register the event listener
        document.addEventListener("backbutton", onBackKeyDown, false);
  }
  function onBackKeyDown() {
  	history.back();
	return false;
  }
</script>
<script data-minified="true" src="js/jquery.mobile-1.1.0.min.js"></script>



手机环境下jQuery的DOM性能问题

使用jQuery的选择器,在PC环境下效果比较理想,但在手机环境下DOM选择会比较卡,如果选择器使用频繁,会造成用户UI响应变化滞后。 jQuery默认不会缓存DOM选择,每次使用选择器都会从根节点进行检索,因此,强烈建议缓存DOM选择结果。

例如标签页效果,未优化前:



$("#fhdcList a").each(function(index){
	$(this).click(function(){
		$("#fhdcList a.ui-btn-active").removeClass("ui-btn-active");
		$("#fhdcList a:eq(" + index + ")").addClass("ui-btn-active");
		$(".fhdcTab:visible").hide();
		$(".fhdcTab:eq(" + index + ")").show();
	});
});



这样在循环时每一句语句都会对DOM树从头到尾查找一遍。在PC环境下看不出时延,但在手机环境下切换时明显有点卡。这需要优化:



var tab = $(".fhdcTab");
var listdiv = $("#fhdcList");
listdiv.find("a").each(function(index){
	$(this).live('tap',function(event) {
		listdiv.find("a.ui-btn-active").removeClass("ui-btn-active");
		tab.hide();
		tab.eq(index).show();
		listdiv.find("a:eq(" + index + ")").addClass("ui-btn-active");
	});
});