零配置
webpack 自带的 css-loader 组件,自带了 CSS Modules,没有其他依赖,开箱即用,同时也提供了一些配置选项,通过简单的配置就可以生成你想要的css!
开启
vue-loader指南中讲到,必须通过向 css-loader 传入 modules: true 来开启:
// webpack.config.js
{
module: {
rules: [
// ... 其它规则省略
{
test: /\.css$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
// 开启 CSS Modules
modules: true,
// 自定义生成的类名
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
]
}
}
或
// vue.config.js
module.exports = {
css: {
loaderOptions: {
css: {
modules: {
modules: true
}
}
}
}
}
但实践中发现,不需配置也可使用,大概是版本有更新
全局使用
1.直接在main.js中引入global.module.css
// main.js
import './global.module.css'
2.:global(.classname)
// global.module.css
// .red为局部css
.red {
color: red;
}
// .blue为全局css
:global(.blue) {
color: blue
}
3. xx.vue文件中使用:
<div :class="global.red">app.vue</div>
<div class="blue">app.vue</div>
3.结果
可以发现,
第一行的文字颜色仍是黑色,.red没有生效,
第二行的文字颜色已经设置成了蓝色,.blue成功生效
局部使用
上面例子中的.red没有生效,因为它是局部作用域,那怎么让它生效呢?
在.vue或.js文件等需要使用的地方中,把该 css 或其它预处理文件 —— 以 .module.(css|less|sass|scss|styl) 结尾的 —— 作为 CSS Modules 导入 (用一个变量接收),eg:
import styles from './foo.module.css'
// 所有支持的预处理器都一样工作
import sassStyles from './foo.module.scss'
<template>
<div id="app">
<div :class="global.red">app.vue</div>
<div class="blue">app.vue</div>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import globalModule from './global.module.css'
export default {
name: 'App',
components: {
HelloWorld
},
data() {
return {
globalModule
}
},
created() {
console.log(globalModule)
// {red: "global-module_red_39Ula"}
}
}
</script>
composes
/* colors.css */
.primary {
color: #720;
}
.secondary {
color: #777;
}
/* other helper classes... */
/* submit-button.css */
.common { /* font-sizes, padding, border-radius */ }
.normal {
composes: common;
composes: primary from "../shared/colors.css";
}
优点
css的正常打开方式的弊端
实际开发中,我们往往会碰到下面这些情况:
/* components/submit-button.css */
.Button { /* all styles for Normal */ }
.Button--disabled { /* overrides for Disabled */ }
.Button--error { /* overrides for Error */ }
.Button--in-progress { /* overrides for In Progress */
<button class="Button Button--in-progress">Processing...</button>
1.命名混乱:上面的.Button是普通的按钮的样式,其他三个是在此基础上的样式叠加。如果要增加一种新的按钮,命名也是像上面一样。当程序变得更复杂,或多人协作开发,html中的类名就会很长,不但混乱不易阅读,还影响项目的压缩。 2.依赖管理不好:以上面为例,button的组件有一个css,一个html页面的多个组件,就有多个这种引入语句,就会显得很乱。 3.全局污染:当项目趋于复杂,有些类名多个组件共用,有些类名单个组件局部使用,这样管理就会变得混乱。而且多人协作后引入好几个css文件,别人一个样式可能把你写的东西搞得完全认不出来,到时你就知道模块化有多爽了。 4.无法共享样式
CSS Modules 的优点
1.只需简单的命名,不再需要叠加式起名字了。最终生成的类名会根据事先配置好的前缀+唯一的序列码,压缩自然也小一些。
2.依赖管理,不会污染。
3.composes可复用
增加一些配置
1.css.requireModuleExtension去掉文件名中的 .module
// vue.config.js
module.exports = {
css: {
requireModuleExtension: false
}
}
2.css.loaderOptions.css 自定义生成类名,所有的 css-loader 选项在这里都是支持的,例如 localIdentName 和 camelCase:
// vue.config.js
module.exports = {
css: {
requireModuleExtension: false,
loaderOptions: {
css: {
// 注意:以下配置在 Vue CLI v4 与 v3 之间存在差异。
// Vue CLI v3 用户可参考 css-loader v1 文档
// https://github.com/webpack-contrib/css-loader/tree/v1.0.1
modules: {
// 默认配置为'[name]_[local]_[hash:base64:5]'
// name 是文件名,local是类名
localIdentName: 'ph_local_[hash:base64:5]'
},
localsConvention: 'camelCaseOnly'
}
}
}
}
3.css.loaderOptions.[sass|scss|less].prependData向预处理器 Loader 传递选项(globalVars变量)
以sass/scss、less为例,向所有 Sass/Less 样式传入共享的全局变量:
// vue.config.js
module.exports = {
css: {
loaderOptions: {
// 给 sass-loader 传递选项
sass: {
// @/ 是 src/ 的别名
// 所以这里假设你有 `src/variables.sass` 这个文件
// 注意:在 sass-loader v7 中,这个选项名是 "data"
prependData: `@import "~@/variables.sass"`
},
// 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
// 因为 `scss` 语法在内部也是由 sass-loader 处理的
// 但是在配置 `data` 选项的时候
// `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
// 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
scss: {
prependData: `@import "~@/variables.scss";`
},
// 给 less-loader 传递 Less.js 相关选项
less:{
// http://lesscss.org/usage/#less-options-strict-units `Global Variables`
// `primary` is global variables fields name
globalVars: {
primary: 'orange',
blue: 'blue',
green: 'green'
}
}
}
}
}
// main.js
import Vue from 'vue'
import App from './App.vue'
// import './global.css'
+ import './global.less'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
.red {
color: @primary;
}
:global(.blue) {
color: @green
}
生效