视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
在vue中使用css modules替代scroped的方法
2020-11-27 22:17:49 责编:小采
文档

前面的话

css modules是一种流行的模块化和组合CSS的系统。 vue-loader提供了与css modules的集成,作为scope CSS的替代方案。本文将详细介绍css modules

引入

最开始使用Vue的时候,提倡并大量使用的是scoped这种技术

<style scoped>
 @media (min-width: 250px) {
 .list-container:hover {
 background: orange;
 }
 }
</style>

这个可选 scoped 属性会自动添加一个唯一的属性 (比如 data-v-21e5b78) 为组件内 CSS 指定作用域,编译的时候 .list-container:hover 会被编译成类似 .list-container[data-v-21e5b78]:hover

但是,它并不能完全避免冲突

<span data-v-0467f817 class="errShow">用户名不得为空</span>

以上面的代码为例,使用scoped之后,它在元素上添加了一个唯一的属性'data-v-0467f817',CSS样式被编译如下

.errShow[data-v-0467f817] {
 font-size: 12px;
 color: red;
}

但是,如果用户也定义了一个errShow类名,会影响到所有定义为errShow类名的组件的显示

而CSS modules则做的更彻底,它不是添加属性,而是直接改变类名

<span class="_3ylglHI_7ASkYw5BlOlYIv_0">用户名不得为空</span>

这样,大大降低了冲突的可能性,只要不是用户直接给span标签设置样式,基本上不会影响组件的显示

模块化

CSS Modules既不是官方标准,也不是浏览器的特性,而是在构建步骤中对CSS类名选择器限定作用域的一种方式(通过hash实现类似于命名空间的方法)。类名是动态生成的,唯一的,并准确对应到源文件中的各个类的样式

实际上,CSS Modules只是CSS模块化的一种方式。为什么我们需要CSS模块化呢?

CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。于是,亟待解决的就是样式冲突(污染)的问题。一般地,为了解决冲突,会把class命名写长一点,降低冲突几率;加上父元素的选择器,来范围等

CSS模块化就是来解决这个问题的,一般地,分为三类

1、命名约定类

该类CSS模块化方案主要用来规范CSS命名,最常见的是BEM,当然还有OOCSS等,在构建工具出现之前,大多数都是在CSS命名上做文章

2、CSS in JS

彻底抛弃CSS,用javascript来写CSS规则,常见的有styled-components

3、使用JS来管理样式

使用JS编译原生的CSS文件,使其具备模块化的能力,最常见的就是CSS Modules

随着构建工具的兴起,越来越多的人开始使用后两者方案,书写CSS时,不用再特意地关心样式冲突问题。只需要使用约定的格式编写代码即可

写法

下面来介绍CSS modules的写法

在style标签中添加module属性,表示打开CSS-loader的模块模式

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

在模板中使用动态类绑定:class,并在类名前面加上'$style.'

<template>
 <p :class="$style.red">
 This should be red
 </p>
</template>

如果类名包含中划线,则使用中括号语法

<h4 :class="$style['header-tit']">类别推荐</h4>

也可以使用数组或对象语法

 <p :class="{ [$style.red]: isRed }">
 Am I red?
 </p>
 <p :class="[$style.red, $style.bold]">
 Red and bold
 </p>

更复杂的对象语法

 <ul 
    :class="{
 [$style.panelBox]:true,
 [$style.transitionByPanelBox]:needTransition
 }"

更复杂的数组语法

 <li
 :class="[
 $style['aside-item'],
 {[$style['aside-item_active']]:(i === index)}
 ]"

配置

css-loader关于CSS modules的默认配置如下

{
 modules: true,
 importLoaders: 1,
 localIdentName: '[hash:base]'
}

可以使用vue-loader的cssModules选项为css-loader进行自定义的配置

module: {
 rules: [
 {
 test: '\.vue$',
 loader: 'vue-loader',
 options: {
 cssModules: {
 localIdentName: '[path][name]---[local]---[hash:base:5]',
 camelCase: true
 }
 }
 }
 ]
}

下载本文
显示全文
专题