本人使用vue引入css modules做实践。vue文档查看:https://vue-loader-v14.vuejs.org/zh-cn/features/css-modules.html 以及 https://vue-loader.vuejs.org/zh/guide/css-modules.html#%E7%94%A8%E6%B3%95
简单的配置css-loader
{ loader: 'css-loader', options: { modules: true, importLoaders: 1, localIdentName: '[name]_[local]_[hash:base64:5]', camelCase: true } }
然后 <style>
上添加 module
属性,就自动生成一个$style的计算属性可以用了
<template> <p :class="$style.red"> <span :class="$style.redBg" >This should be red</span> </p> </template> <style module> .red { color: red; } .red-bg{ color: #A52A2A } </style>
基本使用没有问题,自己弄个小demo也可以。再实际使用中遇到了坑
引用的第三方组件element-ui不支持css module如何处理?
element-ui这个组件库目前是不支持css modules的。使用默认的css modules后,element中的css文件都改成了css module形式,但是使用时html代码却没有用。比如下面这个alert弹窗。
导致找不到样式,完全错乱了。
解决方案:
让需要进行css modules的文件才进行css modules
//专门针对node_modules中的样式处理 { test: /.css$/, use: ['vue-style-loader', 'css-loader'], include:[path.resolve(__dirname, '../node_modules')] }, { test: /.css$/, use: ['vue-style-loader', { loader: 'css-loader', options: { modules: true, importLoaders: 1, localIdentName: '[name]_[local]_[hash:base64:5]', camelCase: true } }], exclude:[path.resolve(__dirname, '../node_modules')] }
这种方式是比较简单,但是也够粗暴。所有满足条件的文件夹下面的文件都会进行css modules【不管有没有为style添加module都会css modules,只是添加了module会得到一个计算属性$style】。但是情况往往不是那么简单的,复杂场景见下面的坑。
顺利引入了Elment-ui,现在想要再本地覆盖某个element-ui的样式?工程中某些样式不想使用css modules又该如何?
比如
//element-ui的tab切换焦点样式为 .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active { color:#409EFF; background-color: #FFF; border-right-color: #DCDFE6; border-left-color: #DCDFE6; } //你要想在更改这个颜色在本地改写为 .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active { color:#ff0; }
不好意思,本地的样式全部会转换为css modules,而element上的样式class还是原来的样子。打包之后两个class已经不一样了,无法覆盖
还有本地某个样式不想使用css modules。比如common.scss有公用的按钮样式,想直接拿来用,不想再在当前文件建立一个新的样式。比如
// common.scss中公用按钮样式 /* 白底橙字圆角按钮 */ .white-orange-btn{ font-size: 14px; background: $ui-white; color: $ui-main; } // common.scss在入口html已经引用,在test.vue中直接使用,和css modules混用 <template> <div> <button :class="['white-orange-btn', $style.btn]">按钮</button> </div> </template> <style module> .btn{ width: 200px; height: 40px; } </style>
common.scss也不属于node_modules,也进行了css modules,这里直接使用字符串‘white-orange-btn’是找不到的。而‘$style.whiteOrangeBtn’在本地也没有定义。
所以上面两种情况,要解决的问题是:在vue的单文件组件内部,要能指定某些样式进行从css modules,某些样式不进行css modules。
解决方案:
使用 oneOf
规则并在 resourceQuery
字符串中检查 module
字符串
// webpack.config.js -> module.rules { test: /.css$/, oneOf: [ // 这里匹配 `<style module>` { resourceQuery: /module/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { modules: true, localIdentName: '[local]_[hash:base64:5]' } } ] }, // 这里匹配普通的 `<style>` 或 `<style scoped>`或者其他外部css { use: [ 'vue-style-loader', 'css-loader' ] } ] }
这样只有为style设置了module的才会进行css modules,其他情况不会进行css modules。
【注】:如果style中使用lang="scss",则需要对.scss也要进行类似的配置