项目中(样式冲突),如何解决

2,782 阅读1分钟

CSS问题

每个通过vue-cli创建的Vue.js应用都内置了两个极好的解决方案:Scoped CSS 和 CSS Modules.

scoped样式

只需要在style标签上添加一个scoped属性,就可启用scoped样式

<template>
</template>
<style scoped>
</style>

缺点:

  • 如果子组件的根元素上有一个类已经在这个父组件中定义过了,那么这个父组件的样式就会泄漏到子组件中。
  • 有时需要对子组件的深层构造设置样式,需要用到>>>选择符
  • 父组件无scoped属性,子组件带有scoped,父组件是无法操作子组件的样式的
  • 父组件有scoped属性,子组件无,父组件也无法设置子组件样式,因为父组件的所有标签都会带有唯一标志,但子组件不会带有这个唯一标志属性
  • 父子组件都有,同理也无法设置样式,更改起来增加代码量

总结:

失去了组件的封装效果,组件内的所有的title类的样式都会被这些样式所渲染。

CSS Module

CSS Modules加入了局部作用域、依赖管理,这些恰恰解决了基本CSS的最大痛点,避免了全局污染和样式冲突,能最大化的结合CSS生态和JS模块化能力

使用方法:

首先,CSS Modules 必须通过向 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]'
            }
          }
        ]
      }
    ]
  }
}

然后在你的 <style> 上添加 module 特性

<template>
    <span :class="$style.button"/>
</template>

<style module>
.button {
    color:red
}
</style>

解析:所有创建的类可以通过这个组件的$style对象获取。

使用模块化的css,等于告诉vue-template-compiler和vue-cli的webpack配置要对这一部分采用那些相关的loader。

好处:

  • 在html中查看这个元素时,会知道它所属的时哪个组件。
  • 一切都变成显式的,便于操作
  • 可以定义变量,用:export导出

CSS module如何对组件设置样式

<template>
    <BasePanel :class="$style['pricing-panel']"/>
</template>

<style module>
.pricing-panel {
    color:red
}
</style>