萝三画室

教程:在vue-cli中使用less的三种方式:写入单文件、引入和全局变量

最近做的两个项目中,尝试在vue-cli中引入less进行css预处理。常用写入单文件、import引入less文件的形式使用less。然而这两种方法都无法优雅地解决不同vue组件之间的less变量共享问题。然后我就去寻找在vue中全局引用less变量的方法,看到了一篇博客解决了这个问题。
本文基于这篇博客,细化了该博客中一些表达粗略的地方,简化了思考过程,同时也一并介绍了其他两种常用的使用less的方法。关于less的介绍及语法,本文不再细说,我们只讲引入vue-cli项目的方式。相信通过这篇精简的教程,我们可以在vue-cli项目中使用less更加得心应手。

安装

打开cmd,cd进入你的vue-cli项目目录,安装less及less-loader。

1
npm install less less-loader --save

项目中其他任何配置文件都无需修改,这些配置信息vue已经事先帮你写好了。
因此,在less及less-loader安装成功后,我们就可以直接在项目中使用less了

使用

写入单组件

我们知道,在一个vue-cli项目中,一个.vue文件就可以理解为一个单组件。以vue-cli新建的默认app.vue为例,单组件的内容结构是template+script+style:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
#app {
color: #2c3e50;
}
</style>

其中,style标签内应写入的是该组件使用的样式(如果标签内不加scoped属性,则标签内的样式可以跨组件复用)。

将less写入单组件,只需要在style标签内加上属性

1
2
3
4
5
6
7
8
```
<style lang='less'>
@mainColor: #2c3e50;
#app {
color: @mainColor;
}
</style>

使用这种方式需要注意:在单组件内定义的less变量,作用域仅限于该组件,无法跨组件使用。

引入

第二种使用方式就是将样式写入.less文件,通过

1
2
3
4
5
6
7
8
9
10
11
12
```
//GlobleLessVarables.less
@mainColor: #2c3e50;
//app.vue
<style lang='less'>
@import './assets/GlobleLessVarables.less';
#app {
color: @mainColor;
}
</style>

这在一定程度上缓解了方法1带来的多组件共用less变量的问题,但是并没有从根本上解决问题。当共用的组件很多时,我们只能每个文件都import一次。这时我们就可以考虑使用全局less变量。

全局less变量

事实上,less的options中提供了全局变量这一选项,全局变量以key:value形式定义。打开vue-cli项目目录/build/utils.js,找到

1
2
3
4
5
6
7
8
9
10
```
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}

这里我们需要修改返回值中less的值:

1
2
3
4
5
6
7
8
9
10
11
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less',{
'mainColor': '#2c3e50' //修改处在此,全局less变量以key:value形式定义
}),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}

重启node服务器,在app.vue中就可以直接使用less变量mainColor了:

1
2
3
4
<style lang='less'>
#app {
color: @mainColor;
}

为了便于维护,我们也可以将全局less变量整体写入一个.less文件,然后将其解析为一个键值对形式的对象,再传入utils.js。

比如:

  1. 将一些全局less变量写入GlobleLessVarables.less,存放在项目目录/src/assets文件夹中

    1
    2
    3
    4
    5
    6
    //项目目录/src/assets/GlobleLessVarables.less
    @baseHeight: 40px;
    @basicEdgeWidth: 2px;
    @tabClickHight: 5px;
    @contentEdge: 15px;
    @agentNavColor: #606060;
  2. 准备一个方法,用于将less文件转换为键值对形式的对象。这里直接参考vux中的get-less-variables.js,将以下代码存为get-less-variables.js文件,放置于项目目录/build文件夹中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //项目目录/build/get-less-variables.js
    const fs = require('fs');
    module.exports = function getLessVariables(file) {
    var themeContent = fs.readFileSync(file, 'utf-8')
    var variables = {}
    themeContent.split('\n').forEach(function(item) {
    if (item.indexOf('//') > -1 || item.indexOf('/*') > -1) {
    return
    }
    var _pair = item.split(':')
    if (_pair.length < 2) return;
    var key = _pair[0].replace('\r', '').replace('@', '')
    if (!key) return;
    var value = _pair[1].replace(';', '').replace('\r', '').replace(/^\s+|\s+$/g, '')
    variables[key] = value
    })
    return variables
    }
  3. 在utils.js中引入
    修改utils.js:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //项目目录/build/utils.js
    //新增
    const getLessVariables = require('./get-less-variables')
    //修改exports.cssLoaders的return值
    return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less',{
    globalVars: getLessVariables('src/assets/GlobleLessVarables.less')//修改
    }),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
    }

目前这种方法的无法实现热加载,每次更改.less文件,都需要重启node服务器才能体现变更。

——本节完——