摘录自无线Web开发经验谈
针对移动端的web开发主要基于移动端的浏览器,不管安卓还是IOS的浏览器都是基于webkit的,因此移动端开发可以说是针对webkit浏览器的开发。
HTML
- meta-viewport
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimun-scale=1, user-scalable=1"/>
移动端浏览器通常都会设置一个“布局视口”,它的宽度通常很大,比如980px,这样就使得小屏的移动设备能够一次性完整地展示pc端的页面,避免出现横向滚动条。
但是为了针对移动端进行开发,我们需要通过viewport来设置视口的宽度及其他属性。
- width=device-width将视口宽度设置为设备宽度,而不是那个虚拟的宽度。
- user-scalable为yes/no,或者1/0表示是否允许用户缩放。
- initial-scale用于设置Web页面的初始缩放比例,设为1.0则将显示未经缩放的Web文档。>1将放大,<1将缩小
- maximum-scale和minimum-scale用于设置用户对Web页面缩放比例的限制。值的范围为0.25至10.0之间。
- input标签
针对input标签的一些类型,移动端可以弹出对应的键盘。
- text:文本 此类型说明输入框为文本信息,对应的键盘而言,Android和ios都会弹出全键盘。
- password
- button、checkbox、radio、reset、submit都可以使用
- email、search、tel、url等类型,这些标签的外观和text类型一致
CSS3
如果说起手机Web的CSS,就需要说起-webkit-的前缀的CSS的属性。这些前缀是专门为了webkit核心的浏览器设置的属性,可能很多-webkit-的属性,已经成功通用的属性了,不需要再加前缀。不过为了兼容低版本的浏览器,在设置的时候,还是需要加上-webkit-前缀。
hover与active
移动端不支持:hover和:active伪类,因此要实现这个效果的话,可以在body上添加ontouchstart:
<body ontouchstart>
或者直接给body绑定一个ontouchstart事件:
document.body.addEventListener('touchstart', function () { //...空函数即可});
参考依据是:
By default, Safari Mobile does not use the :active state unless there is a touchstart event handler on the relevant element or on the
<body>
.
布局
- flex
- position:fixed
- :before、:after
before和after原先在w3c的定义中,主要在节点的前面和后面插入一段内容,因此在before和after中必须要有content的属性以及数值。
渲染
- 2d渲染:
- border-radius
- box-shadow
- text-shadow
- linear-gradient
- border-image
- 3d渲染
3D的最大的好处,它使用了硬件加速功能。因此在做页面动画的时候使用translate3d(),可以有效开启硬件加速,使渲染性能更好,动画更流畅。
具体可以参考CSS动画的性能优化
动画
由于网页的DOM的特性,动画是非常消耗性能的,再加上网页是单进程单线程的,因此所有的程序运行都会在一根ui线程里运行。手机上的性能还没有达到PC上的性能,因此动画的性能问题在手机上显得异常突出。
js
- 使用document.querySelector和document.querySelectorAll
Zepto
对于jquery大家应该会非常的熟悉,在web手机上也有一个轻量级的类库工具,那就是Zepto,它的很多api接口保持和jquery的接口兼容,其体积非常小,gzip的包在10k左右,非常适合在手机上的无线环境中加载。移动事件
- orientationchange :设备方向旋转时触发的事件
- touchstart、touchmove、touchend、touchcancel
通过这些事件,可以模拟出各种用户的手势,不过由于其处理比较复杂,可能模拟最多的是tap事件
在移动端safari中,click事件会有300ms的延迟,原因就是浏览器需要判断用户这次点击是否是双击,如果300ms内用户没有进行下一次点击那么才判断为单击事件。
因此一般使用zepto的tap事件来替代click事件
- scroll
这个事件在PC上的触发时机和手机上的触发时机不同,scroll事件在手机上,只有在滚动停止的时候才会发生,因此这个事件在移动端用的比较少,因为触发的时机已经晚了。对于需要在移动中,改变页面结构的功能,用scroll是无法完成的。
基础知识
meta标签
这些meta标签在开发webapp时起到非常重要的作用
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="black" name="apple-mobile-web-app-status-bar-style" />
<meta content="telephone=no" name="format-detection" />
- 第二个meta标签是iphone设备中的safari私有meta标签,它表示:允许全屏模式浏览;
- 第三个meta标签也是iphone的私有标签,它指定的iphone中safari顶端的状态条的样式
- 第四个meta标签表示:告诉设备忽略将页面中的数字识别为电话号码
开发技巧
retina屏
- 物理像素:设备的真实像素,比如iPhone 5的分辨率640 x 1136px。
- css像素:css代码中使用的逻辑像素。
设备像素比dpr = 物理像素/css像素,这里retina屏的dpr就是2.
对于retina屏,2个物理像素才表示一个css像素,因此一个200*300的div在设备上就需要400*600的区域来表示。因此一个正常的图片,在retina屏上就会显示的模糊一些。
这里主要考虑使用CSS sprites来优化:
使用媒体查询,在正常分辨率下加载的是@1x图像,而在retina屏下加载的就是@2x图像,即二倍图,二倍图的尺寸是正常图像即单倍图的二倍。
span.location {
background: url(location.png) no-repeat 0 0;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min-device-pixel-ratio: 2) {
span.location {
background-image: url(location@2x.png);
background-size: 16px 14px;
}
同时注意在使用二倍图的时候要规定background-size,以正确定位图片。
首屏速度
第一次打开h5页面的时候,与pc相比,要下载许多图片、音频等资源,首屏速度很有可能会非常慢,不做处理的话就会有很长一段时间的白屏。
除了与浏览器性能优化相同的手段如减少请求数、压缩、使用缓存等方法外,移动端还有自己的一套优化哲学。
以下是我在做h5时采用的一些方案:
js、css内联
省去请求预加载+loading页面
预加载维护一个资源列表,我这里是h5中需要的所有图片。预加载程序会去加载所有图片,加载完成的数量与总量的比值还可以用作loading页面的加载数据。当所有图片都加载完成时进入首屏。
我是用的是前端资源预加载并展示进度条这个工具。
原理其实也相当简单,就是维护一个资源列表,挨个去加载列表中的资源,然后在每个资源加载完成的回调函数中更新进度即可。
loader.prototype.start = function(){
for(int i=0;i<resources.length;i++){
var image = new Image();
image.onload = function(){
this.loaded();
}
image.src = resources[i].url;
}
}
loader.prototype.loaded = functon(){
this.currFinish++;
if(this.currFinish == this.total){
//加载完成!
}
}
加载过程的优化
浏览器显示页面的过程: 首先是DNS解析,然后建立TCP连接,接着下载HTML内容以及资源文件,最后才是整个页面的渲染
这四个阶段分别可以通过dns-prefetch、subresource、prefetch、prerender来帮助浏览器优化性能
- DNS prefetch
dns-prefetch可以指示浏览器去预先解析DNS域名。这样可以减少将要打开页面的延迟。
DNS 请求需要的带宽非常小,但是延迟却有点高,这点在手机网络上特别明显。预读取 DNS 能让延迟明显减少一些。
DNS Prefetching特性允许开发者手动控制,告诉浏览器需要解析哪个域名:
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//google-analytics.com">
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//platform.twitter.com">
也可以通过在服务器端发送 X-DNS-Prefetch-Control 报头来开启DNS预读取:
X-DNS-Prefetch-Control: on
X-DNS-Prefetch-Control: off
- prefetch
允许开发者在页面加载的时候预先加载他们希望指定的页面或元素:
<link rel="prefetch" href="http://daker.me/2013/05/hello-world.html" />
<link rel="prefetch" href="http://daker.me/assets/images/avatar.png" />
- prerender
可以用prerender来让浏览器在后台事先渲染好整个页面,这样它的打开速度将会是0秒!
<link rel="prerender" href="checkout.html">