Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何开发一个移动web UI组件库:适配篇 #82

Open
youngwind opened this issue Aug 13, 2016 · 1 comment
Open

如何开发一个移动web UI组件库:适配篇 #82

youngwind opened this issue Aug 13, 2016 · 1 comment

Comments

@youngwind
Copy link
Owner

youngwind commented Aug 13, 2016

前言

屏幕尺寸适配一直是移动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里面的改变了两个全局变量。那么我页面当中的所有其他元素都必须按照这个基准进行,这样我们在嵌入第三方内容的时候就会很不方便。比如:

  1. 地图问题 ios使用scale后,调用高德地图,地图也会被缩掉,怎么解决? amfe/lib-flexible#54
  2. 我们引入了一个第三方的UI组件库(或者我们自己写一个UI组件库),要是不遵照这个体系来就完蛋了。(目前我写的那个UI组件库也是强依赖于flexible)

天猫与淘宝

既然rem有一些问题,那么有替代方案吗?flexbox布局很早就出来了,迟迟不能广泛使用还是因为兼容性的问题。但是天猫已经率先使用了,可以参考如何看待手机天猫首页改用 flex 布局?与手机淘宝首页的 Rem 方案相比有何优缺点?
在回答”flexbox能否提到rem“这个问题之前,我仔细对比天猫的首页和淘宝的首页,会发现一些有趣的东西。
下图分别是iPhone5s和iPhone6p的对比图。(竖着排版对比不方便,建议把图片下载下来切换对比)
淘宝5s
淘宝6p
天猫5s
天猫6p

我们可以观察到一个现象:
对于天猫而言,6p比5s显示的内容显然要更多。对于淘宝而言,6p与5s显示的内容几乎是一样多。
为什么会这样呢?按理说这两个网站肯定都做到了适配的啊?

适配的标准

问题的答案在于:**适配的标准不同。**对于淘宝而言,当屏幕变大的时候,适配的效果是”按照比例放大“,元素的宽和高都按倍数增加,所以看到的内容一样多。对于天猫而言,当屏幕变大的时候,适配的效果不是”按照比例放大“,而是高度不变,宽度变化。所以可以看到更多的内容。两个标准都是可以接受的。如果是要做到第一个标准,则需要采取flexible方案,如果要做到第二个标准,则需要采取flexbox方案。

适配的原则

以前我们讨论响应式的标准的时候常常是这样考虑的:”当一个div在小屏幕是这么大的时候,那么在大屏幕下应该是多大呢?“但是,其实这种考虑是片面的。因为真实的需要考虑适配的场景往往不仅仅是div那么简单。比如这个div里面可能是文字,也可能是按钮,也可能是图片等等。我觉得有一个规则非常的好。

文字流式,控件弹性,图片等比缩放。
适配原则

出处:http://www.ui001.com/article/123.html

举例:看刚才天猫的那个例子,中间那”十大金刚“,当屏幕变大的时候,它们只不过是相互之间的距离变大的,”金刚“入口本身的大小是没有发生改变的,这就是所谓的”控件弹性“。而淘宝则不是。上面的图片已经标注出了这种差异。

尾声

说来说去,还是那句话:”生命不息,折腾不止“。关于移动端适配,以后可能有更好的解决方案,但是可以预见的是,依旧会有新的问题冒出来。最近刚刚看了张鑫旭大大写的文章基于vw等viewport视区相对单位的响应式排版和布局,也许会成为未来流行的适配方案。

@vin1992
Copy link

vin1992 commented Dec 15, 2018

我有点疑惑,为什么weui 组件库用的是px单位,不是应该要考虑到跨端适配的问题吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants