Css Modules 是通过对标签类名进行加装成一个独一无二的类名,比如.class 转换成.class_abc_123,类似于symbol,独一无二的键名
Css Scope 是通过为元素增加一个自定义属性,这个属性加上独一无二的编号,而实现作用域隔离。
CSS Modules实现CSS模块化的原理就是根据我们在config文件中定义的类名命名规则给类生成一个独一无二的命名,从而实现作用域的隔离。【相关推荐:vuejs视频教程、web前端开发】
<style module> .title { font-size: 14px; font-family: Microsoft YaHei, Microsoft YaHei-Bold; font-weight: 700; color: #13161b; } .name { display: flex; align-items: center; &-img { width: 24px; height: 24px; border-radius: 4px; } &-text { font-size: 14px; font-family: Microsoft YaHei, Microsoft YaHei-Regular; font-weight: 400; color: #13161b; } } </style>
cell: (h, { col, row }) => { // console.log(style); return ( <span class={style.name}> <img src={testImage} class={style['name-img']} /> <span class={style['name-text']}>{row.name}</span> </span> ); },
标签.name-img 被转化成了_name_img_6hlfj_11等
Vue Loader默认使用CSS后处理器PostCSS来实现Scoped CSS,原理就是给声明了scoped的样式中选择器命中的元素添加一个自定义属性,再通过属性选择器实现作用域隔离样式的效果。
<template> <div class="example">hi</div> </template> <style module> .example { color: red; } </style>
<!-- 用自定义属性把类名封装起来了 --> <style> .example[data-v-f3f3eg9] { color: red; } </style> <template> <div class="example" data-v-f3f3eg9>hi</div> </template>
关于应用,这里只针对介绍Vue3版本内的使用问题
在 Vue3 中,CSS Modules,在 c9ccee2e6ea535a969eb3f532ad9fe89
上增加 module 属性,即a6167d77ee734aaef6dcd2aa69de7b33
。a6167d77ee734aaef6dcd2aa69de7b33
代码块会被编译为 CSS Modules 并且将生成的 CSS 类作为 $style
对象的键暴露给组件,可以直接在模板中使用 $style
。而对于如 5e86aa419b2f64de951546affb43f1b7
具名 CSS Modules,编译后生成的 CSS 类作为 content
对象的键暴露给组件,即module
属性值什么,就暴露什么对象。
<script setup> import { useCssModule } from 'vue' // 不传递参数,获取<style module>代码块编译后的css类对象 const style = useCssModule() console.log(style.success) // 获取到的是success类名经过 hash 计算后的类名 // 传递参数content,获取<style module="content">代码块编译后的css类对象 const contentStyle = useCssModule('content') </script> <template> <div>普通style red</div> <div :class="$style.success">默认CssModule pink</div> <div :class="style.success">默认CssModule pink</div> <div :class="contentStyle.success">具名CssModule blue</div> <div :class="content.success">具名CssModule blue</div> </template> <!-- 普通style --> <style> .success { color: red; } </style> <!-- 无值的css module --> <style module> .success { color: pink; } </style> <!-- 具名的css module --> <style module="content"> .success { color: blue; } </style>
注意,同名的CSS Module,后面的会覆盖前面的。
针对module命名区分,主要也是应用在JSX和TSX的组件中居多
对于 JSX、TSX 组件,由于其没办法用 scoped style,所以 CSS Modules 是个很好的选择:
比如在script里面写h函数,直接使用样式变量
cell: (h, { col, row }) => { // console.log(style); return ( <span class={style.name}> <img src={testImage} class={style['name-img']} /> <span class={style['name-text']}>{row.name}</span> </span> ); },
比如render函数
<script> export default { props: { text: { type: String, default: '' } }, render(h) { return <span class={this.$style.span1}>hello 222 - {this.text}</span>; } }; </script> <style module> .span1 { color: blue; font-size: 40px; } </style>
在Scope或者Module中使用global时
:global()允许括号中声明的选择器命中全局,即其类名不会经过规则封装,因此不受作用域的限制。
实际项目中,当我们希望修改所使用组件库的默认样式时,在使用CSS Modules方案的情况下,就可以通过:global()来修改其默认样式,但是要注意最好外面有一层类封装,否则可能影响全局样式。
深度作用选择器使得父组件的样式可以渗透到子组件,其原理是使用后代选择器。
/* 转化前 */ <style scoped> .a :deep(.b) { /* ... */ } </style> /* 转化后 */ .a[data-v-f3f3eg9] .b { /* ... */ }
实际项目中,当我们希望修改所使用组件库的默认样式时,在使用Scoped CSS方案的情况下,就可以通过深度作用选择器来修改其默认样式。
几种深度左右选择器的写法:
但是在Vue3中,已经作出了改进如下:
深度作用选择器废弃/deep和>>>,使用 :deep(.child-class) 来替代::v-deep
:slotted()选择器支持使用:slotted(selector)来控制slot中的样式
:global()选择器当只有某些规则需要全局起效时,允许不重复声明一个全局作用域的style标签,而是使用:global(selector)来声明为全局样式。
深度作用选择器deep和声明为global样式的区别,深度作用选择器只是为了能让父组件控制子组件样式,而global样式是全局起效的。
CSS Modules | Scoped CSS |
---|---|
需要在vue.config.js中额外配置 | Vue Loader默认支持,无需额外配置 |
通过根据配置的类命名规则,为元素生成独一无二的类名来实现作用域隔离 | 通过给元素自定义hash属性,再使用属性选择器选中元素来实现作用域隔离 |
在style标签中声明module | 在style标签中声明scoped |
支持导入其他module的样式,支持样式组合 | / |
通过:global()来解除作用域的隔离,使样式在全局生效 | 1. 可以定义全局样式,使样式不受作用域约束;2. 可以通过深度作用选择器命中子组件,从而控制子组件的样式 |
以上是Vue3学习之深度剖析CSS Modules和Scope的详细内容。更多信息请关注PHP中文网其他相关文章!