目录
  1. 1. 为什么需要样式穿透
  2. 2. 样式穿透的三种方式
  3. 3. Vue3 组件样式变化
Vue样式穿透总结(更新Vue3私有组件样式变化)

为什么需要样式穿透

当我们创建私有组件时(组件样式标签添加scoped),引用了子组件或 UI 组件,你会发现在我们私有组件并不能直接修改其样式。遇到这种情况,一般有两种解决方式:一是添加全局样式(需要覆盖全局样式时);再者就是样式穿透了(组件样式)。


样式穿透的三种方式

以下三种方式在 Vue3 中均已弃用,详见 Vue3 组件样式变化

  • >>>:适用于css、stylus
  • /deep/:适用于node-sass、less
  • ::v-deep:适用于dart-sass、node-sass、less、stylus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- >>> 用法 -->
<style scoped>
.form-wrap >>> .el-input__inner {
width: 100%;
}
</style>

<!-- /deep/ 用法 -->
<style scoped lang="less">
.form-wrap {
/deep/ .el-input__inner {
width: 100%;
}
}
</style>

<!-- ::v-deep 用法 -->
<style scoped lang="less">
.form-wrap {
::v-deep .el-input__inner {
width: 100%;
}
}
</style>

Vue3 组件样式变化

根据 Vue 的 RFC 文件(意见征求稿)中,以上三种样式穿透方式都已被弃用,将用::v-deep() 简写 :deep() 替代。官方文件详情 => 私有样式改变 RFC

0023-scoped-styles-changes


文稿中大致意思是,最初使用的深度选择器是 >>> ,但某些 CSS 预编译器解析时存在问题,后来切换到 /deep/,曾经添加到 CSS 标准提议 中,后被放弃,为了避免混淆又引入了自定义的组合器 ::v-deep。为了兼容性,vue2 中才保留了其他两种。

在开发新的 vue3 SFC 编译器时,我们注意到 CSS 伪元素实际在语义上不是组合器,伪元素接受参数更符合惯用的 CSS,所以采用了 ::v-deep() 替换,简写 :deep()



注:截止 2022 年 5 月 以上 3 种旧的深度选择器任能在 vue3 项目中使用,但会有警告提示信息;

/deep/ 警告提示


另外 Vue3 中还添加了另外两个伪元素 ::v-slotted()::v-global()。总结如下:

  • ::v-deep() 简写:deep():深度选择器(样式穿透);
  • ::v-slotted() 简写:slotted():插槽选择器;

    Vue3 默认情况下,作用域样式不会影响到 <slot/> 渲染出来的内容,因为它们被认为是父组件所持有并传递进来的。使用 :slotted() 伪类以确切地将插槽内容作为选择器的目标。

  • ::global() 简写:global():全局选择器;

    如果想让其中一个样式规则应用到全局,比起另外创建一个 <style>,可以使用 :global() 伪类来实现。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<style scoped>
/* 深度选择器 */
::v-deep(.foo) {
}
:deep(.foo) {
}

/* 插槽选择器 */
::v-slotted(.foo) {
}
:slotted(.foo) {
}

/* 全局选择器 */
::v-global(.foo) {
}
:global(.foo) {
}
</style>


文章作者: Vincent F0ng
文章链接: https://vincef0ng.cn/post/vue-scoped-deep-css/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Vincent F0ng

评论(支持Markdown)