CSS模块化开发
为什么进行css工程化?因为在vue或react等模块化框架中写作,很容易在不同模块中采用了相同的命名,导致了不同模块之间的样式产生相互覆盖的结果。所以为了解决这个问题,产生了css也模块化的概念。
BEM(Block Element Modify)
规定类的命名规范,给不同的命名按照既定规则加上前缀,以避免冲突类名冲突
缺点:学习成本高 优点:当删除的dom元素时,能快速找到对应的css代码并进行删除
CSS modules
css modules 指的是像import js一样去引入css代码。 打包时,css module是会自动将类名转成hash值,杜绝css类名冲突问题。
只有类名和ID选择器才会被模块化控制
{
loader: 'css-loader',
options: {
modules: true, // 开启模块化
localIdentName: '[path][name]-[local]-[hash:base64:5]'
}
}
作用域 被global包裹起来的类名不会被模块化,只在local(当前模块)生效
.title {
color: red;
}
:global(.title) {
color: green;
}
优点: 学习成本低,只是在编译时触发,与平时写css没差异 100%解决作用域污染问题
CSS In JS
如何避免样式混淆?
style-in-component
通过动态生成一个带有一小段哈希值的css选择器,并将css选择器绑定到对应的标签上。选择器名称和对应的样式会被放到head的style标签内存储。
radium
也会动态生成一小段带哈希值的css选择器,但是,其具体样式会放到对应标签上,而不是放到head的style中存储。
完全用js语言去编写css,放在组件内部,从而实现模块化。
优点:
- 学习成本低,和写css差异不大
- 可以传入js变量,使得根据变量编写动态样式更加方便 缺点:
- 运行时编译,会造成一定的运行开销,而且css代码是在客户端生成,所以首屏时间会比较长
- 代码可读性差:自动生成的选择器比较难找到对应的元素,功能组件和样式混淆比较难看
- 对于伪类的处理比较麻烦
预处理器 sass、less
本质上打包结果都是和原生css一样,只是对开发者更加友好
优点:
- 更加方便高效地编写css代码,因为提供了变量、函数、嵌套、混合、继承、层级等功能。也更易于维护和组织代码结构。
- 可读性好,结构清晰,易于拓展
区别:
- 语法区别,定义变量的方式不同
- 支持程度不同:less和sass只支持运算符,颜色处理,字符串处理;stylus支持更多特性和功能
- 编译方式不同:sass和less要先转换成标准的css代码,stylus则在浏览器中动态解析和执行
Vue Scoped
使用该方法后,css只在当前组件中生效,父组件样式不会渗透到子组件中。但父组件的css样式能影响子组件的根节点样式。
另外,父组件可以利用深度作用选择器影响子组件样式:
可以使用 >>> 操作符:
<style scoped>
a >>> .b { /* ... */ }
</style>
有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 或 ::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。
一般情况下,样式隔离的方案是组合使用,比如可以组合使用
BEM+预处理器CSS Moduls + 预处理器
实现原理: 每一个组件都会生成一个[data-v-hash:8]插入HTML标签内,子组件不仅有自己的[data-v-hash:8],也有父组件的。
如果父组件和子组件的选择器完全一样,那么子组件样式会被父组件覆盖,因为子组件优先于父组件mounted。