CSS为什么要模块化开发?有几种方式?

238 阅读3分钟

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,放在组件内部,从而实现模块化。

优点:

  1. 学习成本低,和写css差异不大
  2. 可以传入js变量,使得根据变量编写动态样式更加方便 缺点:
  3. 运行时编译,会造成一定的运行开销,而且css代码是在客户端生成,所以首屏时间会比较长
  4. 代码可读性差:自动生成的选择器比较难找到对应的元素,功能组件和样式混淆比较难看
  5. 对于伪类的处理比较麻烦

预处理器 sass、less

本质上打包结果都是和原生css一样,只是对开发者更加友好

优点:

  • 更加方便高效地编写css代码,因为提供了变量、函数、嵌套、混合、继承、层级等功能。也更易于维护和组织代码结构。
  • 可读性好,结构清晰,易于拓展

区别:

  1. 语法区别,定义变量的方式不同
  2. 支持程度不同:less和sass只支持运算符,颜色处理,字符串处理;stylus支持更多特性和功能
  3. 编译方式不同: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。