如何开发一个移动web UI组件库:适配篇
youngwind opened this issue · 1 comments
前言
屏幕尺寸适配一直是移动web开发的大问题,在进行UI组件库的开发的时候,必然绕不过这个问题。不过,我想跳出组件库的范畴,从更广泛的角度谈一谈移动端屏幕尺寸适配。
流行多年的rem
基于rem的适配方案在数年前就已经兴起,并且一直沿用至今,较为系统的代表是淘宝的flexible 。
关于如何使用这套体系,前人之述备矣。我就不赘述了。 下面重点说一下我的使用体会。
适配与dpr无关
问题:在flexible体系当中引入dpr的概念,但是却又在代码中强制指定所有安卓的dpr都是1。如下代码片段。
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}
为什么要这么做?
官方的说法是:当时安卓很多机型的dpr都是假的。参考这里
然而,我们从这儿也可以发现:即便设置的dpr与安卓机真实的dpr不同,但是适配方案仍然能正常工作。也就是说,设置的dpr与真实的dpr是否相等其实根本不影响此适配方案
我们还可以从源代码的另一方面来佐证这个结论。
// line 51
scale = 1 / dpr;
// line 58
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
// line 68
var width = docEl.getBoundingClientRect().width; // 这个width是会根据scale按倍数缩放的
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
发现没?其实本质上是先通过根元素的fontSize放大dpr倍,然后再通过viewport的scale缩小dpr倍,仅此而已。
既然dpr不影响适配,那么方案中为什么要引入它?
答案:是因为要同时解决“1px边框问题”和“高清图片问题”了,具体的可以参考这篇文章。
rem的弊端
flexible改变根元素的fontSize和viewport的scale,相当于js里面的改变了两个全局变量。那么我页面当中的所有其他元素都必须按照这个基准进行,这样我们在嵌入第三方内容的时候就会很不方便。比如:
- 地图问题 amfe/lib-flexible#54
- 我们引入了一个第三方的UI组件库(或者我们自己写一个UI组件库),要是不遵照这个体系来就完蛋了。(目前我写的那个UI组件库也是强依赖于flexible)
天猫与淘宝
既然rem有一些问题,那么有替代方案吗?flexbox布局很早就出来了,迟迟不能广泛使用还是因为兼容性的问题。但是天猫已经率先使用了,可以参考如何看待手机天猫首页改用 flex 布局?与手机淘宝首页的 Rem 方案相比有何优缺点?
在回答”flexbox能否提到rem“这个问题之前,我仔细对比天猫的首页和淘宝的首页,会发现一些有趣的东西。
下图分别是iPhone5s和iPhone6p的对比图。(竖着排版对比不方便,建议把图片下载下来切换对比)
我们可以观察到一个现象:
对于天猫而言,6p比5s显示的内容显然要更多。对于淘宝而言,6p与5s显示的内容几乎是一样多。
为什么会这样呢?按理说这两个网站肯定都做到了适配的啊?
适配的标准
问题的答案在于:**适配的标准不同。**对于淘宝而言,当屏幕变大的时候,适配的效果是”按照比例放大“,元素的宽和高都按倍数增加,所以看到的内容一样多。对于天猫而言,当屏幕变大的时候,适配的效果不是”按照比例放大“,而是高度不变,宽度变化。所以可以看到更多的内容。两个标准都是可以接受的。如果是要做到第一个标准,则需要采取flexible方案,如果要做到第二个标准,则需要采取flexbox方案。
适配的原则
以前我们讨论响应式的标准的时候常常是这样考虑的:”当一个div在小屏幕是这么大的时候,那么在大屏幕下应该是多大呢?“但是,其实这种考虑是片面的。因为真实的需要考虑适配的场景往往不仅仅是div那么简单。比如这个div里面可能是文字,也可能是按钮,也可能是图片等等。我觉得有一个规则非常的好。
出处:http://www.ui001.com/article/123.html
举例:看刚才天猫的那个例子,中间那”十大金刚“,当屏幕变大的时候,它们只不过是相互之间的距离变大的,”金刚“入口本身的大小是没有发生改变的,这就是所谓的”控件弹性“。而淘宝则不是。上面的图片已经标注出了这种差异。
尾声
说来说去,还是那句话:”生命不息,折腾不止“。关于移动端适配,以后可能有更好的解决方案,但是可以预见的是,依旧会有新的问题冒出来。最近刚刚看了张鑫旭大大写的文章基于vw等viewport视区相对单位的响应式排版和布局,也许会成为未来流行的适配方案。
我有点疑惑,为什么weui 组件库用的是px单位,不是应该要考虑到跨端适配的问题吗?