因为之前对css Modules不太了解,认识它还得从一个bug说起。

缘起

自己搭的一个vue+ts项目,使用到了swiper,版本号为

"swiper": "^5.4.5",
"vue-awesome-swiper": "^4.1.1",

官方文档main.ts中引入

import VueAwesomeSwiper from 'vue-awesome-swiper';
import 'swiper/css/swiper.css'
Vue.use(VueAwesomeSwiper /* { default options with global component } */);

demo也是直接copy

<template>
    <div class="hello">
        hello
        <swiper ref="mySwiper" :options="swiperOptions">
            <swiper-slide>Slide 1</swiper-slide>
            <swiper-slide>Slide 2</swiper-slide>
            <swiper-slide>Slide 3</swiper-slide>
            <swiper-slide>Slide 4</swiper-slide>
            <swiper-slide>Slide 5</swiper-slide>
            <div class="swiper-pagination" slot="pagination"></div>
        </swiper>
    </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class HelloWorld extends Vue {

    swiperOptions = {
        pagination: {
            el: '.swiper-pagination',
        },
        cssMode: false,
        // Some Swiper option/callback...
    };
}
</script>

然后发现swiper光有js效果,没有css样式。

img1

于是在资源中查看

img2

果然,这个样式加了一串前后缀,由于不知道这是css Modules造成的,百度搜索也无果,于是继续探索。

解决问题

既然是js从node_modules引入这个样式后自动更改了类名,那我本地引入是否会变?显然这个想法有点天真,试了下同样会更改。举个最简单例子,直接在main.ts同级目录新建一个css文件,然后js引入,同样会有类名被更改。

由此怀疑是开发编译过程中进行的更改,那是谁?webpack。本工程是vue-cli构建的,所以从vue.config.js入手,发现这里有css配置。然后发现requireModuleExtension比较可疑,注释看看。

运气很好,将其注释之后,样式出现了

img3

requireModuleExtension和css Modules

问题到此解决了。不过引申出新的知识:requireModuleExtension是啥?下面是vue-cli官网的相关描述:

css-requiremoduleextension

CSS Modules

简单来说,css Modules和Vue的scoped很像,是用来处理样式全局化的问题。因为在单页中,只有一个html,引入样式后会对页面上的所有命中的css样式生效。但单页中实际上是有多个视图或者页面的,他们应该有自己的作用域,组件间可以相互隔离,于是有了这些方案。

这里有篇比较详细的介绍了CSS Modules,点击前往

阮一峰-css Modules

回到vue的requireModuleExtension设置,默认情况下它是true,意思是你想用css Modules,就要是*.module.[ext] 的文件。比较有无module的区别。

<template>
    <div id="app">
         <div :class="styles.mycss">mycss</div>
         <div :class="styles1.mycss">mycss1</div>
    </div>
</template>

<script>
import styles from './mycss.css';
import styles1 from './mycss.module.css';
export default {
    name: 'app',
    data() {
        return {
            styles,
            styles1,
        };
    },
};
</script>

结果发现styles.mycss样式是不生效的。

如果设置requireModuleExtension为false,就是说所有css,scss,less等文件都认为是 CSS Modules 模块。此时styles.mycss和styles1.mycss都是生效的。

后话

注意,使用CSS Modules好处在于可以在js中作为模块引入,使用对象的方式引入css类名。

缺点也很明显,就是书写css代码不是很直观,最大的问题是文章开头的现象,它可能在引入第三方库的CSS文件时,由于默认会将CSS模块化,导致真正的样式无法生效。


大白菜
36 声望3 粉丝