css moudle及其在vue项目中的使用

scoped css

在Vue项目中,一般使用 scoped 属性来创建样式模块。带有scoped属性的样式模块只会作用于当前组件的元素。

CSS 复制代码
<template>
    <div class="example">
        <p>这是一个段落</p>
    </div>
</template>

<style scoped>
.example {
    color: red;
}
</style>

最终页面效果如下:

这是借助vue-loaderPostCSS 实现的.

不过这种方式存在缺陷: 如果你子组件的根元素上有一个类已经在这个父组件中定义过了,那么这个父组件的样式就会泄露到子组件中。例如:

Parent.vue:

vue 复制代码
<template>
  <div class="container">
    <p>parent</p>
    <child />
  </div>
</template>

<script>
import Child from "./components/Child";
export default {
  name: "App",
  components: {
    Child,
  },
};
</script>
<style scoped>
.container {
  color: red;
  border: 1px solid blue;
}
</style>

Child.vue

vue 复制代码
<template>
  <div class="container">
    <p>child</p>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
};
</script>
<style scoped>
</style>

为什么Child会受到Parent样式的影响? 可以看到经过loader处理后的html代码如下,如果父子组件都使用了scoped,那子组件的根元素也会有父组件的data-v-hash属性,会对子组件造成污染.

xml 复制代码
<div data-v-4184d4e3 class="container">
    <p data-v-4184d4e3>parent</p>
    <div data-v-00d89a5e data-v-4184d4e3 class="container">
        <p data-v-00d89a5e>child</p>
    </div>
</div>

css moudle

vue 复制代码
<template>
  <div :class="$style.container">
    <p>child</p>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  mounted() {
    console.log(this.$style);  // {container: '_src_components_Child__container'}
  }
};
</script>
<style module>
.container {
  color: green;
}
</style>

上面的模板在经过loader处理后的html为:

html 复制代码
<div data-v-4184d4e3 class="_src_components_Child__container">
    <p>child</p>
</div>

可以看到生成的class类名 _src_components_Child__container文件路径+文件名+css类名 ,确保了class类名不会重复. 在模板中可以通过$style获取所有的样式.

可以明显看到使用css moudle的优点:

1、可以一眼看出样式属于哪个组件

2、不会让父组件的样式泄漏到子组件

实际上它还有一些其它的功能:

组合样式

对于样式复用,CSS Modules 只提供了唯一的方式来处理:composes 组合

css 复制代码
/* components/Button.css */
.base { /* 所有通用的样式 */ }
.normal {
  composes: base;
  /* normal 其它样式 */
}
.disabled {
  composes: base;
  /* disabled 其它样式 */
}

import styles from './Button.css';
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

由于在 .normalcomposes.base,编译后会 normal 会变成两个 class

html 复制代码
<button class="button--base-daf62 button--normal-abc53">Submit</button>

composes 还可以组合外部文件中的样式

css 复制代码
/* settings.css */
.primary-color {
    color: #f40;
}
/* components/Button.css */
.base { /* 所有通用的样式 */ }
.primary {
    composes: base;
    composes: primary-color from './settings.css';
    /* primary 其它样式 */
}
通过 :global 声明为全局样式
css 复制代码
:global {
  .global-class-name {
    color: green;
  }
}

在webpack中配置css moudle

只使用css moudle:

javascript 复制代码
{
  module: {
    rules: [
      // ... 其它规则省略
      {
        test: /.css$/,
        use: [
          'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              // 开启 CSS Modules
              modules: true,
              // 自定义生成的类名
              localIdentName: '[local]_[hash:base64:8]'
            }
          }
        ]
      }
    ]
  }
}

同时使用scope和css moudle:

perl 复制代码
// 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>`
    {
      use: [
        'vue-style-loader',
        'css-loader'
      ]
    }
  ]
}
相关推荐
A_Bin2 分钟前
前端工程化之【包管理器】
前端
小肚肚肚肚肚哦4 分钟前
CSS 伪类函数 :where 简介
前端·css
Nick56835 分钟前
Swift -- 第三方登录之微信登录 源码分享
前端
麦麦大数据12 分钟前
D026 vue3+django 论文知识图谱推荐可视化系统 | vue3+vite前端|neo4j 图数据库
前端·django·vue3·知识图谱·推荐算法·论文文献·科研图谱
小肚肚肚肚肚哦19 分钟前
伪元素与普通元素的层级关系问题浅析
前端·css
梦想CAD控件1 小时前
网页CAD中组(Group)功能的二次开发
前端·javascript·github
讨厌吃蛋黄酥1 小时前
🔥 JavaScript异步之谜:单线程如何实现“同时”做多件事?99%的人都理解错了!
前端·javascript·面试
华仔啊1 小时前
别再纠结Pinia和Vuex了!一篇文章彻底搞懂区别与选择
前端·vue.js
徐同保2 小时前
Redux和@reduxjs/toolkit同时在Next.js项目中使用
开发语言·前端·javascript
~无忧花开~2 小时前
CSS学习笔记(二):CSS动画核心属性全解析
开发语言·前端·css·笔记·学习·css3·动画