为什么需要样式穿透
当我们创建私有组件时(组件样式标签添加scoped
),引用了子组件或 UI 组件,你会发现在我们私有组件并不能直接修改其样式。遇到这种情况,一般有两种解决方式:一是添加全局样式(需要覆盖全局样式时);再者就是样式穿透了(组件样式)。
样式穿透的三种方式
以下三种方式在 Vue3 中均已弃用,详见 Vue3 组件样式变化。
>>>
:适用于css、stylus
/deep/
:适用于node-sass、less
::v-deep
:适用于dart-sass、node-sass、less、stylus
1 | <!-- >>> 用法 --> |
Vue3 组件样式变化
根据 Vue 的 RFC 文件(意见征求稿)中,以上三种样式穿透方式都已被弃用,将用::v-deep()
简写 :deep()
替代。官方文件详情 => 私有样式改变 RFC。
文稿中大致意思是,最初使用的深度选择器是 >>>
,但某些 CSS 预编译器解析时存在问题,后来切换到 /deep/
,曾经添加到 CSS 标准提议 中,后被放弃,为了避免混淆又引入了自定义的组合器 ::v-deep
。为了兼容性,vue2 中才保留了其他两种。
在开发新的 vue3 SFC 编译器时,我们注意到 CSS 伪元素实际在语义上不是组合器,伪元素接受参数更符合惯用的 CSS,所以采用了 ::v-deep()
替换,简写 :deep()
。
注:截止 2022 年 5 月 以上 3 种旧的深度选择器任能在 vue3 项目中使用,但会有警告提示信息;
另外 Vue3 中还添加了另外两个伪元素 ::v-slotted()
和 ::v-global()
。总结如下:
::v-deep()
简写:deep()
:深度选择器(样式穿透);::v-slotted()
简写:slotted()
:插槽选择器;Vue3 默认情况下,作用域样式不会影响到
<slot/>
渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用:slotted()
伪类以确切地将插槽内容作为选择器的目标。::global()
简写:global()
:全局选择器;如果想让其中一个样式规则应用到全局,比起另外创建一个
<style>
,可以使用:global()
伪类来实现。
1 | <style scoped> |