前端是一个非常庞大和复杂的领域。
如果说多年前的前端只是需要学习几个 HTML 标签,看到别的网站用了狂拽酷炫的特效就 copy 下来,稍微懂点 jQuery 做日常使用,再了解几个 Prototype 和 MooTools(貌似都不再维护了)等高冷脱俗的库做装X用就能显得很“专家”了。那么现在要还是持这样的想法,就不适合搞前端。
且不说 JavaScript 在与时俱进,更新出了 ES6,增加了茫茫多的特性,用 CSS 也可以做一些简单动画了。当一个新的 JS 库或者框架发布时,它可能在 0.x 的版本就能火起一片天,又或者马上出现竞争对手,多的是我们听都没听过的工具。另一方面,连我们使用的设备也从 PC 的一统天下慢慢转成了移动端的主场。
收,这篇文章的重点还是在于如何去考虑做移动端的响应式布局。
响应式(Responsive Web Design)是一个很早就出现的概念,当时人们就预想到 mobile 的占有率会飙升吧。 它指的是同一个页面能够适应不同尺寸的屏幕进行布局。 这里说尺寸是因为我们大部分时间是在关注屏幕大小,而不是它用的是多少比例的屏幕、设备的颜色深度等等,所以其他一些用途就没必要说了,实行一下28原则吧(20% 的概念可以解决 80% 的问题)。
然后说 Hybrid 应用,它同样不是一个新词。很多专注于业务而非性能的 APP 都会采用这种方式去开发。它指的是用前端技术(HTML, CSS, JS)配合中间件(比如 cordova)去开发一个移动端应用。因为 WebView 的存在使这些都成为了现实。
它并不是什么高深的技术,只要稍微懂点英文单词,根据它 官方文档 描述的内容,花半天去看就能配出一个 apk 来了。
难的永远不是框架或者工具,而是思考问题的角度和解决问题的方式。
毕竟从 apk 走到产品还是有很长一段路的。
前端的同学应该对兼容性是恨透了,那做混合型应用的话就很少会有兼容性问题了,然而换来的却是另一个问题——屏幕适配。
移动端屏幕尺寸的碎片化非常严重,小的有 320 * 480,大的有 1920 * 1080,然后你知道手机都支持旋转的吧,所以这些尺寸的宽高对调一下又是一副新面孔。但只要有问题就有解决办法,毕竟市面上那么多页面都显示的好好的,它们是怎么做到的呢?
乔布斯还活着的时候,他坚持认为 3.5 英寸的手机是最符合人体工学的,但我们知道,iphone 4s 比 iphone 3gs 的像素高。这是因为有个度量单位叫 PPI (Pixels per Inch) ,指的是每英寸的长度上有多少像素。
也就是说 320 * 480 的屏幕上一个像素,相当于 640 * 960 的屏幕上的四个像素。如果纯粹按照像素来算的话,显然后者可以在同样大小的屏幕上显示更多内容,这会导致有些内容甚至小到看不清。
我们希望对于同样物理大小的屏幕,能有相同的布局,尽管他们的实际像素可能差几倍。所以这里又有一个 倍率 的概念。之前提到响应式中的尺寸,就宽度来说的话,有两种,一个是 width,另一个是 device-width 。前者是实际宽度,比如某手机屏幕的宽是 1080 像素;后者指的是按照倍率缩放之后的宽度,比如这款手机是 3 倍率的,那么 device-width 就是 360 像素了。
很多大屏手机,或者不同分辨率的手机,经过倍率的换算之后,device-width 是相当统一的。
所以这就是为什么我们会在手机端的页面上设置如下标签:
html
<meta name="viewport" content="width=device-width, initial-scale=1">
就是为了让 CSS 在设置大小(盒子宽高、行高、间距、字体大小等)时,按照 device-width 而不是实际像素来计算。
这样子的话,同样的页面,在 1 倍率的 320 * 480 屏幕,和在 3 倍率的 960 * 1280 屏幕上会有一模一样的布局。
至于如何计算这个缩放比例,很简单,用
javascript
window.devicePixelRatio
一般桌面浏览器的 devicePixelRatio 是 1,手机上就会有 1.5, 2, 3 等值,然后与
javascript
screen.width
结合换算一下就能得到我们需要适配的屏幕宽度了。
首先需要明确的一点是,我们是 针对屏幕尺寸布局,而不是针对设备布局 。
所以,如果用 @media 做判断的话,不需要针对 iphone 几,或者 samsung 多少而无谓增加各种条件,只需要问自己,在 320 像素、360 像素、768 像素等宽度的屏幕中,页面应该做怎样的调整。
各位应该都知道,响应式布局中有一个“断点”的概念,就是说,假设有
css
@media (max-width: 768px) { /* 针对 768px 宽以下的屏幕 */ }
那么 768px 的宽度(如果在 meta 中设置了 width=device-width,这里的宽度就指的是 device-width)就是一个临界点,小于等于 768px 的屏幕会执行这段 css,而大于 768 px 的屏幕就不会。
可能说屏幕大家会误会,手机端的屏幕宽度就是视口(viewport)宽度,因为它不支持调整窗口大小,而 PC 端的浏览器可以调大小,那屏幕宽度确切地来说应该是视口宽度了,也就是网页可视区域的宽度。
至于你应该怎样去挑选断点,就需要根据应用场景来决定了。我一般是开了 Firefox 的响应式设计模式,那里预置了很多尺寸,如果用户对象是移动端,那么 360 * 640 就挺常见的。如果不知道应该怎么选的话,可以尝试用一下。
既然是做响应式,那么很多兼容性问题都不需要考虑了,毕竟只有 IE 9+ 才支持 @media 指令,那手机端就更不用说了。
CSS 3中新增了 transform 和 transition 这两个和动画相关的属性。以往如果要实现将一个方框从 100 * 100 放大到 200 * 200,可能需要用 JS 去定时改变 style 中的 width 和 height 属性,后果是每次 style 的改变都会引发 DOM 重绘。用 transition 可以这么来做:
css
.box { width: 100px; height: 100px; transition: all ease-in .3s; } .box.active { width: 200px; height: 200px; }
需要放大的时候,通过 JS 给 .box 加上 active 类就可以了,GPU 会帮你完成过渡效果。当然,深入研究的话还有很多知识可以讨论,只不过我想引出的就是, 能用 CSS 完成的效果就不要用 JS 去做 ,各司其职。
性能,经常看博客的同学可能都知道:压缩 CSS 和 JS,做 sprite 图,将图片(要优化的话,图片往往是重头)部署到静态资源服务器,用 CDN,等等。
但是那么多条条框框下,我们可以做到什么?对于很多前端工程师来说,这些事情是不需要自己去做的,公司中自然有专门的构建工具帮你部署。在学校中的同学,从来不会考虑这些方面,甚至没有专门做前端的,就像本文开头所说的,从别的网站上挪几段样式表过来。
然后,我们比较两款产品,搜狗输入法和QQ输入法(好吧,虽然跟前端没太大关系)。如果尝试过各种输入法的话,你会发现搜狗输入法的启动速度很慢。我无数次卸载过,换成必应输入法、百度输入法、QQ输入法……但他们的皮肤都没搜狗做的好,于是又可耻地装了回来。
所以我觉得比性能更重要的产品特色。可能做前端的不会去多考虑产品相关的领域,但具体问题具体分析,不要为了刻意去提高性能而花很多工时在优化上。计算机界不是有句话很有名么:
过早的优化是万恶之源。
并不是说不需要提高性能了,而是说,搞清楚什么时候该做什么事情。
倒是有些优化在编码的时候就能做到的,就比如之前所说的利用 CSS 动画而非 JS 去模拟。在用高级的 CSS 属性时,想一想代价,能用低级的属性就用低级的。意思就是说,用 flex 可以实现任何布局,但它的计算代价非常大,所以不到万不得已就不用。
如果能保持一种代码整洁的强迫感,那在优化这条路上就会走的很顺畅吧。
(小结放到文章开头了……)