css modules的一些实践

本人使用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也要进行类似的配置

 

posted @ 2020-03-18 21:20  chua1989  阅读(634)  评论(0编辑  收藏  举报