- 实现原理
自适应布局是前端一直都存在的问题,通常常用的技术有媒体查询
@media screen and (max-width:1366px)
,还有rem布局,通过改变页面根元素font-size
大小来实现自适应布局。可是都逃不过要计算的命运。有没有什么方法绕过这些花花绕,就写px
也能实现自适应布局呢?答案是肯定的,有方案理论上就能实现,这样一来无论是写自适应项目,还是修改原有项目,都变得十分方便。下面看看webpack打包scss的过程:
首先浏览器是无法解析scss
代码的,在项目工程里,通过webpack
的loader
将文件打包成浏览器可执行的代码。比如scss
,首先加载到scss
、sass
文件时,就会通过sass-loader
打包成css
,然后在通过css-loader
打包,具体配置代码如下:
{
test: /\.scss|sass$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
通过这个可以想到,如果有一个
loader
,能够在这些css文件打包前,将文件里面的px
计算成rem
,然后在进行解析,这样就可以直接在页面中使用px
了。主角出场了postcss-px2rem
,可实现这个功能,下面看看在vue
中的具体配置
- 代码分析(这段无需配置)
使用webpack
新建vue
项目时,已经安装好了这个loader
,在build
文件夹下utils
(配置loader
的地方)面有这样一段代码
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less').concat({
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, '../src/assets/styles/global.less')
}
}),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
在generateLoaders
函数中有这样一句usePostCSS
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
然后在通过styleLoaders
构造rules
格式的loader
,所以我们只要把webpack.dev.conf.js
跟webpack.prod.conf.js
文件中使用styleLoaders
函数的参数加一个usePostCSS:true
就可以(默认就有)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
- 配置文件(报错的话记得安装
postcss-px2rem
),在vue-loader.conf.js
配置一下,vue-loader
转换
module.exports = {
//使用px-rem转换
postcss: [require('postcss-px2rem')({remUnit: 100})],
}
- 最后一步,监听窗口大小变化,动态设置
font-size
,定义一个js文件引入main.js
中
// baseSize 要跟vueloade配置的一样
let baseSize = 100
function setFontSize () {
// 设计稿 1920
let scale = document.documentElement.clientWidth / 1920
// 设置页面根节点字体大小,最高放大比例为2)
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
// 初始化
setFontSize()
// 监听窗口变化
window.onresize = function () {
setFontSize()
}
注意:①不能将大小直接写在vue
文件的style
中
②无需转换rem
可以写Px
或者PX