前记
前端三剑客里,无疑css和html的重视程度远低于js,一方面是因为JS是开发中的核心,JS水平的高低往往决定了天花板的高度。另一方面CSS比较简单,做出符合产品需求的样式并不难,而且前端领域不缺轮子,搬搬代码也是极好的(笔者也属于其中)。但大部分都误解的是,CSS虽然好掌握,但也同样功能强大,CSS模块化也随着前端发展而不断向前。
css存在的问题
回想一下,在开发过程中,令人头疼的CSS是不是存在以下几个问题呢。
- 全局污染,样式冲突。明白人都知道,说来都是泪,样式垮掉,多半是这问题。
- 命名。复杂组件或页面里,命名冲突,冗杂。
- 无变量。2017年以后才在CSS里引入变量,早些时候是没有的。
社区解决方案
- less、scss、stylus css预编译语言,提供了譬如变量、嵌套、混合、运算、占位符等方法,对css样式复用、样式抽离起了极大的促进作用。
- BEM 流行的class命名规则,为了解决命名冲突提供了良好的思路。但命令过于冗杂。
- CSS IN JS 顾名思义,CSS不在于JS抽离。最为流行的 styled-component开源库。
- CSS Modules 极大的避免样式冲突,全局污染等问题,存在作用域,利于样式复用。
Vue里scoped、modules比较
scoped
scoped可直接在vue等里使用,会生成带唯一属性来区分。一般情况下是唯一的,不会重复。
值得注意的是,父组件的样式不会应用到子组件中。除非:子组件的顶层container类名和父级
里某个类名相同。
// child.vue
<template>
<div class="red"> // 顶层container 类名存在于父级 渲染出来时红色
<h1>This is a child page</h1>
</div>
</template>
<style scoped>
.red {
color: green; // 绿色
}
// father.vue
<template>
<div>
<h1 class="red">This is a test page</h1>
<child></child>
</div>
</template>
<style scoped>
.red {
color: red;
}
</style>
以上例子说明,也是有可能造成样式冲突的。而解决的方法无疑是增加样式权重 !important。
另外如果只是单纯的使用选择器,而不是class或id会造成性能的丢失。
在使用第三方库,想修改第三方UI样式。有两种选择,
1、不在scoped里做样式;2、深度选择器
深度选择器
- .a >>> .b
- /deep/ (sass,less)
动态内容
v-html生成的内容不受scoped样式影响,可选择深度选择器
modules
书写上用$styles.classname绑定class。
modules不会存在scoped的问题,即使类名相同,也不会影响。
modules可以搭配scss、less使用,功能更加强大和丰富。
使用
在vue里需要额外配置
{
test: /\.css$/,
use: [
'vue-style-loader',
{
loader: 'css-loader',
options: {
// 开启 CSS Modules
modules: true,
// 自定义生成的类名
localIdentName: '[local]_[hash:base64:8]'
}
}
]
}
scoped类名权重问题将不会存在,且在JS里可以通过this.$style.red访问
<template>
<div :class="$style.red">
<h1>This is a child page</h1>
</div>
</template>
<style module>
.red {
color: red;
}
</style>
作用域
// 不会被编译hash字符串
:global(.color) {
color: red;
}
// 会被编译成hash
:local(.color) {
color: green;
}
// 效果一样
.color {
}
总结
以上社区提供的解决方案,各有利弊。适合项目的,才是最好的。目前个人采用CSS Module和sass搭配,感觉很实用,css的问题大多能解决。也有一些个人心得想分享给大家。
1、组件化开发,不仅仅是组件,css也同样可以做到复用抽离。sass提供强大的@mixin、@extend等功能相当实用。
2、尽量使用class、id选择器,不要使用元素选择器。用着一时爽,改时两行泪。
3、贴近项目。不应一味追求使用什么,而应该致力于解决了什么。保质保量完成项目,才是工作的核心。