Mobile web开发之道
移动web开发之道(Android与Iphone)
1、javascript篇
(1)使用querySelector和querySelectorAll这两个方法获取文档对象中DOM节点的引用
由于这两个方法都是本地方法,因此在执行效率上比较理想
//获得一个id为masthead的对象的引用: var masthead = document.querySelector( "#masthead " ); //获得id为banner的UL元素下面最后一个LI元素下的A标签的引用: var anchor = document.querySelector( "#banner > li:nth-last-child(1) > a " ); //获得id为category的UL下面的所有LI元素的引用 var categoryList = document.querySelectorAll( "#category > li " ); |
(2)采用标准的W3C DOM2推荐的事件监听模型监听事件
//推荐的形式: window.addEventListener( "load " , function (e){ console.log( "page loaded " ); }, false ); //不推荐的形式: window.onload = function (e){ console.log( "page loaded " ); } |
(3)HTML5 Form3 标准加入细化的表单控件检测功能(如Email、URL、TEL等表单控件),因此可直接使用内建的此类空间的验证
//Email类型的表单控件: <input id= "email " type= "email " value= " " /> //URL类型的表单控件: <input id= "url " type= "url " value= " " /> //不能为空的表单控件: <input id= "name " type= "text " value= " " /> |
//验证时,调用checkValidity方法查询返回值即可: if (!document.querySelector( "#url " ).checkValidity()){ //failed } |
(4)使用placeholder为表单文本输入框空间提供默认提示值(通常情况下采用脚本操作完成)
为Email类型的表单控件提供一个提示值便于用户识别:
<input id= "email " type= "email " value= " " /> |
(5) 如果需要在用户机器上保存数据,而且数据相对比较大,可以考虑使用本地存储对象localStorage完成
相比cookie而言,localStorage具有编程接口友好,存储空间大等优点
//调用示例: localStorage.setItem( "selectedTabIdx " ,3); //增加一项 localStorage.removeItem( "selectedTabIdx " ); //删除一项 |
(6)使用内建支持的JSON API处理JSON数据
var point = { x:1, y:1 }; //将point对象序列化为JSON串 // {"x":0,"y":1} var coordinate = JSON.stringify (point); //将JSON串反序列化为point对象 var point = JSON.parse(data); |
(7)使用标准的window.scrollY接口来获取滚动条上部表示的文档长度
document.documentElement.scrollTop或者document.body.scrollTop在safarimobile下此值为0
(8)使用__proto__属性实现对象继承
var Shape = function (){ } Shape.prototype = { draw: function (){ //… } } // Triangle继承自Shape var Triangle = function (){ Shape.apply( this ,arguments); } Triangle.prototype = { __proto__:Shape.prototype, draw: function (){ //paint triangle } } |
(9)对基本类型或内建DOM对象的扩展都应建立在对象的基础上
由于智能手机平台的脚本运行环境比较完善和符合规范(如DOM对象都是原生的本地对象,而在常规WEB平台上, IE浏览器的部分JAVASCRIPT对象和DOM对象都是依赖COM组件实现,因此是不能直接扩展这些对象的),例如:去除的字符串首位空白
建议的方法:
String.prototype.trim = function (){ return this .replace(/(?:^\s+|\s+$)/gi, "" ); }; |
调用示例:
var str = " string with leading and trailing whitespace " ; str.trim(); |
不建议的方法:
var trim = function (str){ return str.replace(/(?:^\s+|\s+$)/gi, "" ); }; |
调用示例:
var str = " string with leading and trailing whitespace " ; var str = trim(str); |
(10)在WEBKIT手机平台上,使用DOM 对象操作的效率比innerHTML操作的效率要高
因此通常情况下,优先选择DOM对象操作创建DOM树例如向id为xyz的SPAN元素中添加1000链接, chrome在PC上的执行结果为
//采用innerHTML方式创建 var html = []; for ( var i = 0; i < 1000; i++){ html.push( "<a href=" \"javascript:void(0)\" ">" +i+ "</a>" ); } document.querySelector( "#xyz" ).innerHTML = html.join( "" ); //执行时间为22秒 //采用DOM节点对象操作的方式创建 var c = document.querySelector( "#xyz" ), anchor; for ( var i = 0; i < 1000; i++){ anchor = document.createElement( "a" ); anchor.textContent = i; c.appendChild(anchor); } //执行时间为14秒 |
(11)new WebKitCSSMatrix(window.getComputedStyle(dom).webkitTransform) 新建矩阵
(12)DOMSubtreeModified DOM文档树修改时执行事件,兼容IE9、FF、safari、chrom不支持opera
2、CSS篇
(1)使用CSS3 Media Query可以分别为手机横屏模式(landscape)和竖屏模式(portrait)应用样式, 是布局更加合理
#masthead{ Margin- top : 10px ; } /*单独为横屏(langscape)声明样式*/ @media screen and ( max-height : 300px ){ #masthead{ margin-top : 0 ; } } |
(2) 使用CSS创建渐变的背景图片
.heading{ background : #F5F7FF -webkit-gradient(linear, 0% 0% , 0% 100% , from( white ), color-stop( 0.02 , #FAFCFF ), color-stop( 0.7 , #F4F6FF ), to( #F6F7FF ));} |
(3)使用CSS3多层背景创建相对复杂的icon
.icon::before{ float : left ; margin : 2px 5px 0 0 ; content : "\20" ; width : 4px ; height : 14px ; text-indent : -999em ; background-image :-webkit-gradient(linear, left top , right top ,color-stop(. 0 , #9cdbfa ),color-stop(. 2 , #9cdbfa ),color-stop(. 21 , #58b3df ),color-stop(. 4 , #58b3df ),color-stop(. 41 , #007ac4 ),color-stop( 1.0 , #007ac4 )),-webkit-gradient(linear, left top , right top ,color-stop(. 0 , #9cff65 ),color-stop(. 2 , #9cff65 ),color-stop(. 21 , #5af703 ),color-stop(. 4 , #5af703 ),color-stop(. 41 , #46c500 ),color-stop( 1.0 , #46c500 )); background-position : 0 0 ; background-repeat : no-repeat ; -webkit-background- size : 100% 4px , 100% 100% ; } |
(4)使用webkit提供的css canvas创建简单图片icon,例如:
预先在内存中创建Canvas对象
( function () { var a = 8; var a2 = a / 2; var ctx = document.getCSSCanvasContext( '2d' , 'triangle' , a2 + 2, a); ctx.fillStyle = '#46c500' ; ctx.strokeStyle = "#46c500" ; ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(0, a); ctx.lineTo(a2, a/2); ctx.lineTo(0, 0); ctx.closePath(); ctx.fill(); ctx.stroke(); })(); |
使用CSS引用内存中的Canvas对象:
. icon { background :-webkit-canvas(triangle) 5px 50% no-repeat ; } |
(5)采用base64编码创建小图片、icon
3、目前发现的一些bug
(1)G3(Android 1.5)版本touch事件的问题
G3(Android 1.5)版本,触发touchstart事件之后,并没有触发touchmove事件,直接触发touchend事件。在Android 1.5中,手指点击事件触发正常。但是手指移动时touchmove及touchend无法正常触发,可能情况是触发时间不正确或者事件触发不连续。
解决方案:在touchstart事件中,对于事件参数e调用preventDefault方法,阻止触发浏览器默认事件。
一点疑惑:该问题可能由于move的时候浏览器本身IO阻塞了正常程序的执行,后验证确实会这样,例如阻止链接的点击
(2)Android 对绝对定位在文本框上的元素的ontouchstart事件
Android 对绝对定位在文本框上的元素的ontouchstart事件支持有badcase,当手指点击该元素(文本框内的区域)的时候无法触发该元素的ontouchstart事件,针对Android要用onmousedown解决。
(3)iPhone & Android 不支持position:fixed
(4)某些情况下,使用translate3D进行屏幕翻页操作,会导致屏幕闪烁,解决办法,改用普通的translate,但是会没有硬件加速效果
(5)translate 的bug
发现在某一款ios上会出现此bug,itouch的4.1(8B117),发现在使用translate进行翻页时,翻完后屏幕会闪烁下,使用 translate3d可以搞定这个问题,但是translate3d可能引入更多的问题,例如按钮高亮错误,图片渲染bug等,最后google一顿乱 收,终于找到解决办法:
-webkit-perspective: 1000 ; -webkit-backface- visibility : hidden ; |
(6)JS在点击链接时发送图片请求来记录点击日志bug
但如果链接在当前窗口打开,就会出现日志缺失的情况,因为,如果跳转较快,而图片还没来得及创建,改请求就不会发送
(a)先preventDefault,settimeout执行window.location.href=”"
(b)onmousedown时即创建图片请求
(7)android1.6下scalebug,当css如下写时li为img的父级元素,调用scale后页面空白
li{ overflow : hidden ; float : left ;} img{ position : absolute ;} |
(8)scale会改变坐标系,比较混乱,没搞明白到底什么样的
(9)部分android手机上不能访问内网域名,只能访问ip地址
(10)Android手机window.innerWidth和window.innerHeight的bug
在屏幕旋转时,返回的值并不是当前宽度和高度,而是旋转之前的,通过下面方法可以解决,寻求更好的解决办法:
var orientationEvent=( "onorientationchange" in window) ? "orientationchange" : "resize" ; window.addEventListener(orientationEvent, function (e){ setTimeout( function (){ alert(window.innerWidth); },500); }, false ); |
(11)阻止手机浏览器缩放,在头部设置下述代码,但某些高版本的手机上会失效(G12,G13)
|
(12)字体大小随屏幕旋转而变大,而且只是部分变大
在开发完页面后,在iphone上,正常浏览页面,没有问题,但是当旋转屏幕为风景模式时,发现有些字体变大,而有些则不变,很诡异吧 其实是因为iphone会自适应font-size,解决办法:
html {-webkit-text-size-adjust: none } |
(13)translate使用3d坐标时会出现文字渲染的诡异bug
例如在通过translate进行手机上的翻页功能时, 在safari手机可以看到字体变形,不过这个问题在手机上不会出现
-webkit-transform: translate 3 d( -334px , 0px , 0px ); |
去掉3d后即没问题了
(14)iPhone & Android 不支持position:fixed
解决办法,android上使用user-scalable设置为no,ios5支持,但是ios 4.2.1不好使,寻求高手指教
4、开发工具
(1)fiddler代理
就像pc端的fiddler代理功能一样,手机上也可以使用代理,这样可以更方便的进行远程调试,更多细节:http://www.lovesunlife.com/?p=127
(2)weinre
这个工具非常的强大,也非常的适用,fiddler只能调试可以使用代理的手机,但目前很多android还不能使用代理,这时候不好调试,所以使 用这时就需要使用wenire工具进行远程调试,我使用的是linux机器,下面是weinre linux调试环境安装方法:
(a)下载weinre https://github.com/downloads/phonegap/weinre/weinre-jar-1.5.0.zip
(b)tc-noah-info1.tc /tmp/java6.tar.gz下载
(c)解压缩java6
(d)配置环境变量vim ~/.bashrc
export JAVA_HOME=/home/img/liuhui/java6 export PATH= $JAVA_HOME /bin: $PATH export CLASSPATH=.: $JAVA_HOME /lib/tools.jar: $JAVA_HOME /lib/dt.jar: $CLASSPATH |
(e)java -jar weinre.jar –httpPort 8081 –boundHost -all-
(f)运行后会提示访问地址 例如我的http://10.26.204.20:8081/
(g)在要调试的页面引入js:http://10.26.204.20:8081/target/target-script-min.js#lh
然后通过http://10.26.204.20:8081/client/#lh
上面我搭建了自己的服务,其实官网提供了它自己的服务,只是速度会比较慢,更多详情官网了解http://phonegap.github.com/weinre/
(3)各种书签工具
这个工具可以让你在手机中开启firebug调试、yslow等,但我感觉还是比较适合pc端的调试 http://stevesouders.com/mobileperf/mobileperfbkm.php,这是国外一牛人汇总的各种书签包括 firebug lite和yslow等
(4)在手机上调试还是没法断点,这时候可以在safari中通过修改useragent来进行手机上的仿真
偏好设置-》高级-》选中 “在菜单栏中显示开发菜单 “,这时候在导航条中就可以看到开发了,点击开发-》用户代理-》选择iphone,除了通过浏览器本身的设置来修改useragent外,还可以通过 fiddler修改rules-》user-agent》选择iphone,如果没有需要自己进行配置rules-》customize rules,在user-agent的配置项中增加下行代码,
RulesStringValue(17, "&iphone" , "Mozilla/5.0 (iPod; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7" ) |
更多user-agent值可参考: http://www.zytrax.com/tech/web/browser_ids.htm#safari
以上是汇总别人一些目前开发中遇到的问题,及最终解决办法,对于初学mobile web开发的人,建议可以看下面博客,讲解的非常详细:
Part 2: The mobile developer’s toolkit
Part 3: Designing buttons that don’t suck
Part 4: On designing a mobile webpage
Part 5: Using mobile-specific HTML, CSS, and JavaScript