移动端适配我采用淘宝的一套rem解决方案
源码: https://github.com/amfe/lib-flexible
1、安装 npm i -S amfe-flexible
2、引入meta标签
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
3、然后引入到项目 import ‘amfe-flexible’
4、到这里适配基本解决,但是我们再写的时候量出来的尺寸都需要除以75rem,这样很烦,这时引入插件postcss-px2rem-exclude解决px2rem的问题,为什么引入postcss-px2rem-exclude,而不是px2rem-loader,当你引入第三方插件库的时候你就知道痛点了,这里先不解释原因,下面会解释,先上结果:
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
'postcss-px2rem-exclude': {
remUnit: 75,
exclude: /node_modules|folder_name/i
}
}
}
6、这时重启一下。到这里我们已经实现了移动端适配,并且是基于750的设计稿量出多少写多少px,然后我们引入第三方库也是没问题的,这里我引入echarts和mintUI已经实验过了。
demo源码请见: https://github.com/qiuzhaofeng/flexible-demo
首先咱们先了解一下viewport
移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,在具体一点,就是浏览器上(也可能是一个app中的webview)用来显示网页的那部分区域,
- width:控制 viewport 的大小,可以指定的一个值,如 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
- height:和 width 相对应,指定高度。
- initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。
- maximum-scale:允许用户缩放到的最大比例。
- minimum-scale:允许用户缩放到的最小比例。
- user-scalable:用户是否可以手动缩放。
我们会发现width这个属性,让viewport的宽等于设备的宽,我们都知道移动端的我们设置的css的1px并不等于设备的1px,因为移动端window对象有一个devicePixelRatio属性,也就是设备像素比dpr,他是设备的物理像素与逻辑像素的比例,我们看到的设备的宽度就是设备的逻辑像素,以我们的iphone6和6plus他们的dpr为2、3,那么他们的物理像素对应的就是设备宽*dpr,所以我们设置的css的1px为逻辑像素,是物理像素的2到3倍,(当然这里默认不缩放,横向或竖向比例),这时我就有一个疑问了,那么这么搞不就相当于用我们css设置的1px覆盖dpr大的上面更多的点,解决了适配问题,但是并没有解决更精确更清晰的问题,应该让我们设置的1px等于设备的物理像素不就行了,不错,淘宝rem适配方案在之前有解决这个问题,我们先来看一下:
源码:https://github.com/amfe/lib-flexible/blob/master/src/flexible.js
源码动态生成viewport,并且没有设置width=divice-width,为的是让我们设置的1px等于设备的物理像素,然后结合动态计算的scale来实现充满区域。我们来导入看一下由于动态生成meta,我们把meta标签删掉,
完美解决,让我们的css1px等于了设备的物理像素,但是为什么作者说lib-flexible这个东西已放弃呢,有图有真相
他说存在一定的问题,也没说什么问题,
那我们继续引入第三方插件库试试,
大家会清楚的看到这第三方插件库怎么这么小啊,为什么呢?
我们看下mintUI的源码
再看下他里面的单位
大家可以看到咱们在这欢乐的动态生成viewport,但是第三方库并没有,人家写死的,除了一些flex或百分比布局,其他都是按逻辑像素走的px,放到我们这个按物理像素走的区域上能不小吗?大家不信可以试一下dpr为1的设备,算了,我还是截个图吧
进一步验证了我们的结果,
作者为什么放弃这个lib-flexible动态生成viewport转而在amfe-flexible中写死,我猜其中一个原因应该是干不过许许多多的第三方库。(仅为本人猜测)。
这里有人可能会说把第三方库的px也转成rem,大家想一下,第三方库是按照逻辑像素走的,而这里我们是按物理像素走的,首先大的宽度都不对,更不用说里面的像素了。
到这里我们确定这个lib-flexible再引入第三方库的时候是不可取得,当然我们的项目中一般都会出现第三方库,所以这里我们来回到我们的amfe-flexible。
然后我们这里来说一下为什么选择postcss-px2rem-exclude而不是px2rem-loader
我们首先引入配置一下px2rem-loader,在utils.js
const px2remLoader = {
loader: 'px2rem-loader',
options: {
remUnit: 75
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, px2remLoader, postcssLoader] : [cssLoader, px2remLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
这个插件是将全局的px都转化成rem,这里我们的项目的viewport是写死的,也就是都是按照逻辑像素走的,按照正常思维是没错的,大家可以看下截图
看着没问题啊,但是你看到的这些是用flex布局或者百分比布局的,我们来看下具体到px的,
这个确定、取消的宽度比之前小了一倍,为什么呢?
在不转rem之前,插件里面写死的是40px;而我们转过之后40/75rem,
在iphone6下1rem=37.5px,算出来的就是19.9999px,也就是小了一倍,
出现这种问题的原因当然是我们的rem是按照750设计稿转的,然而mintUI里面并没有和我们的一致,也许人家的适配已经转过了结果就是40px;而我们这里又转一遍,所以就出现了 postcss-px2rem-exclude这个插件,他的目的是不转第三方库,完美解决我们的问题。
到这里我们的移动端适配就介绍完了,这个适配就是按照设备逻辑像素也叫独立像素的适配。