依赖
项目基础配置使用 vue-cli 生成
移动端自适应方案核心:阿里可伸缩布局方案 - lib-flexible
px 转 rem:px2rem,它有 webpack 的 loader:px2rem-loader
开始
首先,我们使用 vue 的脚手架 vue-cli 来初始化一个 webpack 项目
没有安装过 vue-cli 的请先安装 vue-cli
初始化项目,一些选项根据需要选择
vue init webpack my-app
安装所需依赖后安装 lib-flexible 和 px2rem-loader
npm i lib-flexible -S
npm i px2rem-loader -D
完成之后就可以启动项目了
npm run dev
在项目入口文件 main.js
里 引入 lib-flexible
// main.js
import 'lib-flexible'
接下来为了验证 lib-flexible 是否生效,将 App.vue
改成
<template>
<div class="wrapper">
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
<div class="box4"></div>
<div class="box5"></div>
</div>
</template>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<style scoped>
.wrapper div {
height: 1rem;
}
.box1 {
width: 2rem;
background-color: coral;
}
.box2 {
width: 4rem;
background-color: skyblue;
}
.box3 {
width: 6rem;
background-color: palegreen;
}
.box4 {
width: 8rem;
background-color: wheat;
}
.box5 {
width: 10rem;
background-color: darkred;
}
</style>
可以在浏览器中看到如下情况,并且切换设备后依然自适应显示,说明 lib-flexible 已经生效。
实际开发中,我们通过设计稿得到的值单位是 px,所以要将 px 转换成 rem 再写进样式中。至于转换这步工作可以通过很多方式自动化完成。如果你喜欢通过编辑器插件方式,可以去寻找对应编辑器的插件。今天我们使用 px2rem-loader 帮我们完成。
在前面我们已经安装过 px2rem-loader 了。我们需要它处理 .vue 文件里和在 js 里引入的样式文件。
如果我们想让它处理 .vue 文件里的样式,就需要在 vue-loader 的 options 里进行配置。
如果我们想让它处理在 js 中引入的样式,就需要配置相应样式文件的 loader。
在 vue-cli 生成的 webpack 配置中,vue-loader 的 options 和其他样式文件 loader 最终是都是由 build/utils.js
里的一个方法生成的。如下,有兴趣的可以自行研究一下。
// utils.js
exports.cssLoaders = function (options) {
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
我们只需在 cssLoader 后再加上一个 px2remLoader 即可,px2rem-loader 的 remUnit 选项意思是 1rem=多少像素,结合 lib-flexible 的方案,我们将 px2remLoader 的 options.remUnit 设置成设计稿宽度的 1/10,这里我们假设设计稿宽为 750px
// utils.js
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
var px2remLoader = {
loader: 'px2rem-loader',
options: {
remUnit: 75
}
}
// ...
并放进 loaders 数组中
// utils.js
function generateLoaders(loader, loaderOptions) {
var loaders = [cssLoader, px2remLoader]
// ...
修改配置后需要重启测试服务器,然后我们将 App.vue
里原来的 rem 单位换成 px,这样写起来就舒服多了
<style scoped>
.wrapper div {
height: 1rem;
}
.box1 {
/* 750 * 20% */
width: 150px;
background-color: coral;
}
.box2 {
/* 750 * 40% */
width: 300px;
background-color: skyblue;
}
.box3 {
/* 750 * 60% */
width: 450px;
background-color: palegreen;
}
.box4 {
/* 750 * 80% */
width: 600px;
background-color: wheat;
}
.box5 {
/* 750 * 100% */
width: 750px;
background-color: darkred;
}
</style>
依然生效。
关于字体大小
不推荐用rem作为单位, lib-flexible会在html(也就是document.documentElement)上增加一个data-dpr属性,所以对于字体的设置,仍旧使用px作为单位,并配合用data-dpr属性来区分不同dpr下的的大小。
例如:
div {
width: 1rem;
height: 0.4rem;
font-size: 12px; // 默认写上dpr为1的fontSize
}
[data-dpr="2"] div {
font-size: 24px;
}
[data-dpr="3"] div {
font-size: 36px;
}
至此,我们就创建了一个移动端自适应的项目。
这里使用的是 vue-cli 生成的 webpack 配置,也可以自行编写 webpack 配置。
px 转 rem 仍然是添加 px2rem-loader,就不再多做演示了。
有疑问或错误的地方欢迎指出。