如何在嵌套SCSS &__*规则中使用Vue的:deep()选择器?
Vue中SCSS嵌套&__*规则下:deep()的正确用法
问题背景
我正尝试将Vue.js单文件组件中的部分样式从::v-deep语法迁移到:deep(),但在搭配带&__*的嵌套SCSS规则时遇到了问题(无&__*的规则可正常运行),使用的SCSS编译器为dart-sass。
原代码(有警告但编译正确):
::v-deep .wrapper { &__element { /* 样式代码 */ } }
这段代码会被正确编译为[data-v-S0m3Ha5h] .wrapper__element,但会收到官方警告:
[@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead.
尝试两种迁移方式均失败:
- 将
:deep()放在顶层规则时,dart-sass会尝试生成:deep(wrapper)__element,这不是有效CSS选择器,直接编译报错; - 将
:deep()移到嵌套规则时,编译无错误,但生成的CSS不符合预期:.wrapper[data-v-S0m3Ha5h] &__element。
解决方案
方案1:使用@at-root结合插值语法
这是最贴近原有嵌套写法的解决方案,能保留嵌套结构同时生成正确的CSS:
:deep(.wrapper) { /* .wrapper的基础样式 */ @at-root #{&}__element { /* .wrapper__element的样式 */ color: #333; } }
编译后会生成预期的:
[data-v-S0m3Ha5h] .wrapper { /* ... */ } [data-v-S0m3Ha5h] .wrapper__element { color: #333; }
原理:#{&}会将父选择器:deep(.wrapper)插值为字符串,再与__element拼接,@at-root将拼接后的选择器提升到根级别,Vue编译器会正确解析:deep()部分,生成带作用域属性的选择器。
方案2:拆分嵌套结构
如果不需要保留嵌套结构,直接拆分两个:deep()规则更简单:
:deep(.wrapper) { /* .wrapper的基础样式 */ } :deep(.wrapper__element) { /* .wrapper__element的样式 */ color: #333; }
这种写法直观易懂,适合样式结构不复杂的场景。
方案3:使用SCSS变量复用选择器
如果需要多次复用选择器,可通过变量存储避免重复编写:
$base-selector: .wrapper; :deep(#{$base-selector}) { /* .wrapper的基础样式 */ } :deep(#{$base-selector}__element) { /* .wrapper__element的样式 */ color: #333; }
这种方式能提升代码可维护性,尤其当选择器名称较长或需要批量修改时。
内容的提问来源于stack exchange,提问作者sjaustirni
相关产品推荐
相关产品推荐

