头闻号

法兰美化妆品(珠海)有限公司

粉底|胭脂|唇膏|眼影|睫毛膏

首页 > 新闻中心 > 科技常识:实现移动端响应式布局
科技常识:实现移动端响应式布局
发布时间:2024-11-15 11:45:39        浏览次数:3        返回列表

今天小编跟大家讲解下有关实现移动端响应式布局 ,相信小伙伴们对这个话题应该有所关注吧,小编也收集到了有关实现移动端响应式布局 的相关资料,希望小伙伴们看了有所帮助。

单位选择: vw 还是 rem ?

我们选择了 rem 作为像素单位。因为本次开发的项目包含 ipad 与手机端,使用 rem 单位应对的根元素字体可以根据设备动态设置。因此 ipad 端与手机端公共的样式只需要写一套代码就能实现,而使用vw作为单位在无论什么情况下都需要写2套样式,见下面的例子:

假设现在2倍视觉稿上有一个显示 500*300 的按钮,而这个按钮在ipad端和手机端的样式相同。下面是两种写法的对比:

使用vw作为单位,视觉稿上手机宽度为 750,ipad宽度为 2048

.button.phone { width: 100 * 500 / 750vw; height: 100 * 300/ 750vw;}.button.ipad { width: 100 * 500 / 2048vw; height: 100 * 300/ 2048vw;}

使用rem作为像素单位,根据屏幕的宽度(1024px作为分界点)大于这个像素按ipad的样式做适配,否则按手机设备做适配。设置基数为20,即视觉稿上的html根元素字体大小20px。

let wWidth = document.body.offsetWidth; let html = document.documentElement; let remNum = wWidth < 1024 ? (wWidth / 750) * 20 : (wWidth / 2048) * 20; html.style.fontSize = `${remNum}px`;

因此对于公共的样式只需要写一套代码就行。

.button { width: 500 / 20rem; height: 300 / 20rem;}

当然上述的都是伪代码,less是不支持这种写法 因此最终的代码要这么写:

.button { width: 25rem; height: 15rem;}

手动计算不恶心吗?

每次写样式都要在心里计算一遍单位,如果碰到不能被20整除的单位,只能使用计算器,非常恶心。

好在 less 提供了一套单位转换函数 unit(@px, rem) 将px转化为rem,且它支持四则运算。

因此上述的样式可以这么写:

.button { width: unit(500/20, rem); height: unit(300/20, rem);}

结束了?

这样就结束了?远远不够,每次都要写重复的代码,非常麻烦,可以再节约些吗?

使用less 提供的mixin 封装公共的样式方法:

.button { .w(500); .h(300);}// mixin.w(@px) { width: unit(@px / @baseUnit, rem);}.h(@px) { height: unit(@px / @baseUnit, rem);}

真的结束了吗?

看似解决了重复的问题,但是有引入了新的问题: 设置margin的值,不能连着写, 必须写四个样式,虽然说mixin 支持...arguments 实现动态参数,但别忘记了还需要对参数做单位转化呢,因此不能满足我们的需求。

.button { .mt(10); .mr(10); .mb(10); .ml(10);}

遇到 translate, background-size 等这些不常用的样式,推荐用原始的方式去写。对这种不常用的样式封装意义不大,而且还会增加mixin函数的记忆成本。

.button { translate: (unit(300/20, rem), unit(300/20, rem)); background-size: (unit(300/20, rem), unit(300/20, rem));}

切换成 sass 去避坑

sass自带了自定义函数的功能,可以解决上述问题的痛点。

// px to [email protected] x2r($px) { @return $px * $baseUnit * 1rem;}.button{ width: x2r(500); height: x2r(300); margin: x2r(10) x2r(10); transform: translate(x2r(500), x2r(300));}

唯一的缺点是语法不够优雅:joy:

有最终的解决方案吗?

感觉这样用起来还是很不方便,还达不到完美的境界,有更好的解决办法吗? 最终解决方案:采用 webpack 的 loader 直接完成单位的转换。

.button { width: 500pxr; height: 300pxr; margin: 10pxr 10pxr; transform: translate(500pxr, 300pxr);}// loader 转化后.button { width: 250rem; height: 150rem; margin: 0.5rem 0.5rem; translate: (150rem, 150rem);}

具体思路:对.vue文件与.less 文件中的less代码做一次替换,把pxr单位转换成rem单位。在vue-loader与less-loader之前插入这个单位转化的 loader 完成单位的转化。

// unit-convert-loader.jsconst loaderUtils = require('loader-utils');exports.default = function(source) { const { rembase = 16, isvueFile = false } = loaderUtils.getOptions(this); function replaceStyle(styleStr) { return styleStr.replace(/\d*\.?\d+pxr(?=;|\)|,| )/g, $1 => { const pixels = parseInt($1); return `${pixels / rembase}rem`; }); } // .vue 文件中从 style 标签中获取样式规则进行替换 if (isvueFile) { source = source.replace( /(<style.+>)([\s\S]*)(<\/style>)/g, (_, $1, style, $2) => { return `${$1}${replaceStyle(style)}${$2}`; } ); return `export default ${source}`; } else { // 其他的样式文件,直接进行替换 return replaceStyle(source); }};

不用手动计算单位,不用去记mixin的函数,不用每次写重复的的代码,书写规则更接近于原始,是不是很方便:smile:。

VS postcss-pxtorem

与postcss-pxtorem 做比较,不敢说比它更优秀,但是应该比它更能满足我们目前的业务需求。一旦将来切换到其他项目,单位换成vw,这个工具只需稍微做个拓展,改变下loader中传入的参数也依旧可以支持将单位转换为vw。

结束了

仅仅只是是文章结束了。这种方法还有一些局限性,不支持vue模板中的style语法中的单位转换。不是不能实现,一旦支持但是上面的“replaceStyle” 函数就没法复用,替换的正则表达式会更加复杂,而且即时支持了收益也不大,完全有代替的方案。杀鸡不用牛刀,所以我选择放弃。

最后再附上vue-cli3 自定义loader的配置chainwebpack: config => { config.module .rule('less') .test(/\.less$/) .oneOf('normal') .use('unit-convert-loader') .loader(path.resolve('unit-convert-loader.js')) .options({ rembase: 20 }); config.module .rule('vue') .test(/\.vue$/) .use('unit-convert-loader') .loader(path.resolve('unit-convert-loader.js')) .options({ rembase: 20, isvueFile: true });

原文:https://blog.souche.com/untitled-26/

来源:爱蒂网