移动端开发整理

基本概念

基本概念有几个

  • 物理像素(physical pixel)
  • CSS像素
  • 屏幕密度
  • 设备像素比(device pixel ratio)

物理像素

物理像素应该是到过最多的东西。这归功于厂商宣传的好:

1
2
3
4
5
6
7
8
9
480P:480*320
720P:1028*720
1080P:1920*1080
2K屏:2560*1440
#IOS
4 4s:960*640
5 5c 5s se:1136*640
6 6s:1334*750
6+ 6s+:1920*1080(1080P)

CSS像素

CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。写过CSS的都会知道,这个就是px。

屏幕密度

屏幕密度是指一个设备表面上存在的像素数量,它通常以每英寸有多少像素来计算(PPI)。

设备像素比

1
设备像素比 = 物理像素 / 设备独立像素

在javascript中,可以通过 window.devicePixelRatio 获取到当前设备的dpr。

在css中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。

移动设备调试

移动端设备的调试一直是个比较困扰人的问题。不过好在已经有人对移动端的调试做了总结。具体可以参考这个GithubReop:jieyou/remote_inspect_web_on_real_device

文中提到的内容有以下内容(内容来自上诉repo),基本已经涵盖了各种环境下的调试,包括浏览器,微信,webView——可见作者确实非常有经验:

方法关键点实现难度 为佳)调试效果 为佳)可用的桌面设备可用的移动设备及可调试的浏览器
spy-debugger (简化weinre配置,支持https)需要桌面设备和移动设备同一网段22PC、MAC全部
调试Android上的Chrome需要翻墙24PC、MACAndroid上的Chrome
调试Android APP里的webview需要翻墙34PC、MACAndroid APP里的webview
调试Android上的x5内核(微信等)安装较为繁琐35PC、MACAndroid上的应用了x5内核的app,如微信、手Q、QQ浏览器等
调试Android上的UC需要桌面设备和移动设备同一网段13PC、MACAndroid上的UC
调试iOS上的Safari需要MAC(甚至可以无需iOS设备)24MACiOS上的Safari

移动端适配方案

写之前寻找了下有没有更具体系统的资料,毕竟如果有更系统的资料可以起到很好的借鉴作用。最后发现还是这篇比较系统:MobileWeb

综合来说,是这几种可行方案。

  • 固定高度,宽度自适应
  • 固定宽度,viewport缩放
  • rem做宽度,viewport缩放

具体的细节这里就不具体写了,可以去爬文查看。这里仅仅对实现的原理进行部分总结。有了这个原理就可以做到心中有谱,知道每种方案是怎么回事。

固定高度,宽度自适应

固定高度几乎是从PC端转移动端切图时候瞬间就会想到的方案:

  1. PC端早有百分比布局的实践
  2. 高度可以写死来避免高度不能使用百分比的问题

固定宽度,viewport缩放

固定宽度这个是将viewport的width写死来实现的。设计图、页面宽度、viewport width使用一个宽度,浏览器帮我们完成缩放。单位使用px即可。
这个方案的优点嘛,设好了这块以后,可以完全按照PC端切图的经验来,单位完全可以使用px。
不过不足之处上,原文可能没有指出:在这种方案下做的页面可以相对省事的适配好各种屏幕,但是除了生硬的缩放外和由此来的模糊外,还有一个缺陷是无法做响应式,因为PC端并不认viewport.

rem做宽度,viewport缩放

这个方案是个人最看好的方案。或者是因为对rem充满好感的缘故。
下面是引用的秒速

依照某特定宽度设定 rem 值(即 html 的 font-size),页面任何需要弹性适配的元素,尺寸均换算为 rem 进行布局;当页面渲染时,根据页面有效宽度进行计算,调整 rem 的大小,动态缩放以达到适配的效果。利用该方案,还可以根据 devicePixelRatio 设定 initial-scale 来放大 viewport,使页面按照物理像素渲染,提升清晰度。

个人最喜欢的还是 rem做宽度,viewport缩放 。适配这个东西,算是移动端入门第一步,有了理论打基础整个开发才可能达到得心应手的程度。

REM技术实现方案

目前来说rem方案里面淘宝的amfe/lib-flexible比较出名,而且是实践总结,所以坑相对也会平坦一些。

不过如果不用淘宝的方案,其实自己也可以写js替代它,这是目前个人用过的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
(function (doc, win) {
var docEl = doc.documentElement
var designWidth = 750 // 设计稿宽度
var baseWidth = 320 // 如果 clientWidth 取不到值,给个最小宽度值
var baseFontSize = 100 // Rem 计算基础值,我这里给 100
var giveBaseWidth = 480
var giveBaseFontSize = (giveBaseWidth/designWidth)*baseFontSize
var resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize'
recalc = function () {
var clientWidth = docEl.clientWidth || baseWidth
if (clientWidth > designWidth) clientWidth = designWidth
var fontSize = (baseFontSize*clientWidth/designWidth)
fontSize = fontSize >= giveBaseFontSize ? giveBaseFontSize : fontSize
docEl.style.fontSize = fontSize + 'px'
}
doc.addEventListener
&&
(
win.addEventListener(resizeEvt, recalc, false),
doc.addEventListener('DOMContentLoaded', recalc, false)
)
})(document, window)
</script>

把它加入到head头部就好。然后编辑器设置base值,将px统一手动转换成rem也好,使用编辑器插件也好,总之转换过来就ok了。
不过说实话,每次加这个&&转换也是比较烦的事情,所以如果使用的webpack方案,可以使用 px2rem-webpack-plugin 补丁,这个补丁依赖了html-webpack-plugin,所以如果用了它可以不用自己在安装一次了。

这里简单copy一下文档,归结一下使用方法,具体使用姿势:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var HtmlWebpackPlugin = require('html-webpack-plugin');
var Px2remWebpackPlugin = require('px2rem-webpack-plugin');
var webpackConfig = {
entry: 'app.js',
output: {
path: 'dist',
filename: '[hash].app.js'
},
plugins: [
new HtmlWebpackPlugin(),
new Px2remWebpackPlugin({originScreenWidth: 750}),
]
};

最后生成的html里面是类似这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webpack App</title>
<script>
document.documentElement.style.fontSize = 100 * innerWidth / 320 + 'px'
addEventListener('load', function() {
setTimeout(function(){
document.documentElement.style.fontSize = 100 * innerWidth / 320 + 'px'
window.unit = 100 * innerWidth / 320;
var e = document.createEvent('Event');
e.initEvent('adjustReady', true, true);
window.dispatchEvent(e);
}, 480);
})
addEventListener('orientationchange', function() {
setTimeout(function(){
document.documentElement.style.fontSize = 100 * innerWidth / 320 + 'px'
}, 480)
});
</script>
</head>
<body>
<script src="6062412d2f3140cc3dd0.app.js"></script></body>
</html>

原理和上面差不多,只不过是自动帮你插入代码到了html里面。originScreenWidth: 750这个是设置设计图的宽度。
这个插件怎么说呢,初看,单页的话似乎用途也不太大。但是,它最大的用途其实是将css里面的px转换成rem,这样就不需要依赖编辑器的转换了。

关于HOTCSS

实际上hotcss这小节应该列入rem技术方案那儿的。不过想了想还是把它挪出来单独写了。github地址:hotcss

主要优势:

  • 保证不同设备下的统一视觉体验。
  • 不需要你再手动设置viewport,根据当前环境计算出最适合的viewport。
  • 支持任意尺寸的设计图,不局限于特定尺寸的设计图。
  • 支持单一项目,多种设计图尺寸,专为解决大型,长周期项目。
  • 提供px2rem转换方法,CSS布局,零成本转换,原始值不丢失。
  • 有效解决移动端真实1像素问题。

恩,谈这个之前,还是得感叹一下,前端发展的实在太快了。当我还在使用px2rem很快乐的时候,更先进的东西就不期而至了。
hotcss的readme写了以上的优势,但是并没有说,是针对 的优势,但是想想,实际上它针对的,就是上面写到的rem方案。hotcss是上面rem方案的加强版,官方说是 移动端布局终极解决方案,其实也没什么错,就目前来说,这已经最先进的rem方案。

具体的使用使用方法,由于是国内的开源项目,是中文文档,就不再复制了。

组件化开发

本来到了上章就讲完了。奈何,前端发展太快,我们又有了新的选择。
那就是组件化开发。这个讲起来就相对复杂一些。主要的技术栈是两个:Vue + webpack + vue-router && React+webpack+react-router。简单说,是Vue体系和React体系。

Vue体系下我认为最好的组件库是Vux,因为它足够全面,基本上能想到的组件,难以实现的组件的,它都做好了。怎么说这个全呢?有一次我做一个类似淘宝的快递进度条这个,去看vux的组件库,它都做好了。我认为它是最强的移动端组件库了。这是文档地址

React体系下的移动端UI库,国内我认为最好的应该是Antd Mobile了,延续了ant的文档风格,常见的组件基本都有了,不过相比vux,它的组件丰富程度确实只能算是一般。

就Vue体系来讲,使用vue-cli是一个非常棒的选择,如果是React,阿里加的dva-cli认真讲其实非常不错。不过,就我个人看法来说vue-cli就是比较国际范儿,功能全面支持多种手脚架;相对来说dva-cli就要差一些,不过他对React的redux逻辑封装的非常好,最新的版本都可以生成model了。

不过,如果使用vue-cli也好,dva-cli也好,他们本身都是不带router的,所以,你需要自己去集成它。router+webpack,是按需加载的必要项目,如果你用它们做移动端项目,项目稍大一点,这就是必选项。

——————— THE END ———————

参考文章

移动端适配方案(下)