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'
      ]
    }
  ]
}
相关推荐
SomeB1oody8 分钟前
【Rust自学】6.3. 控制流运算符-match
开发语言·前端·rust
m0_7482567835 分钟前
【Django自学】Django入门:如何使用django开发一个web项目(非常详细)
前端·django·sqlite
林小白的日常1 小时前
uniapp中wx.getFuzzyLocation报错如何解决
前端·javascript·uni-app
傻小胖1 小时前
React 脚手架配置代理完整指南
前端·react.js·前端框架
EterNity_TiMe_1 小时前
【论文复现】农作物病害分类(Web端实现)
前端·人工智能·python·机器学习·分类·数据挖掘
余生H2 小时前
深入理解HTML页面加载解析和渲染过程(一)
前端·html·渲染
吴敬悦2 小时前
领导:按规范提交代码conventionalcommit
前端·程序员·前端工程化
ganlanA2 小时前
uniapp+vue 前端防多次点击表单,防误触多次请求方法。
前端·vue.js·uni-app
卓大胖_2 小时前
Next.js 新手容易犯的错误 _ 性能优化与安全实践(6)
前端·javascript·安全
m0_748246352 小时前
Spring Web MVC:功能端点(Functional Endpoints)
前端·spring·mvc