• 开始时间:2020-01-21
  • 目标主要版本:2.x 、3.x
  • 引用 issue:N/A
  • 实现的 PR:N/A

摘要

在单文件组件中 scoped 的 style 中提供更一致的自定义 CSS 扩展。

基本范例

  1. <style scoped>
  2. /* deep selectors */
  3. ::v-deep(.foo) {}
  4. /* shorthand */
  5. :deep(.foo) {}
  6. /* targeting slot content */
  7. ::v-slotted(.foo) {}
  8. /* shorthand */
  9. :slotted(.foo) {}
  10. /* one-off global rule */
  11. ::v-global(.foo) {}
  12. /* shorthand */
  13. :global(.foo) {}
  14. </style>

动机

Vue 的单文件的 scoped style 使 CSS 仅应用于当前组件。有一些用户经常遇到的情况是可以改进的。

deep 选择器

有些时候,我们可能想明确地让一条规则针对子组件。

最初,我们支持 >>> 组合器使选择器“深入”。然而,一些 CSS 预处理器,如 SASS 在解析它时有问题,因为这不是一个正式的 CSS 组合器。

我们后来改用了 /deep/,它曾经是 CSS 的一个实际提案的附加项(甚至在 Chrome 中原生支持),但后来放弃了。这给一些用户带来了困惑,因为他们担心在 Vue SFC 中使用 /deep/ 会使他们的代码在放弃该功能的浏览器中得不到支持。然而,就像 >>> 一样,/deep/ 只是作为 Vue 的 SFC 编译器重写选择器时的一个提示,并在最终的 CSS 中被删除。

为了避免被丢弃的 /deep/ 组合器的混乱,我们引入了另一个自定义的组合器,::v-deep,这次更明确的支持这是一个 Vue 特定的扩展,并使用伪元素语法,这样任何预处理器都应该能够解析它。

由于兼容性的原因,在当前的 Vue2 SFC 编译器仍然支持以前版本的 deep 组合器,这又会让用户感到困惑。在 Vue3 中,我们正在废除对 >>>/deep/ 的支持。

当我们正在为 Vue3 开发新的 SFC 编译器时,我们注意到 CSS 伪元素实际上在语义上不是组合器。伪元素接受参数更符合 CSS 的习惯,所以我们也让 ::v-deep() 以这种方式工作。如果你不关心明确的 v- 前缀,你也可以使用更短的 :deep() 变体,其工作原理完全相同。

目前仍然支持 ::v-deep 作为组合器的用法,但它被认为是过时的,并会引起警告。

定位/避免 slot 内容

目前,从父组件传过来的 slot 内容既受父组件 scoped 样式的影响,也受子组件 scoped 的样式影响。没有办法编写只针对插槽内容的明确规则,或不影响插槽内容的规则。

在 v3 中,我们打算让子组件的 scoped 样式默认不影响插槽的内容。要明确的针对插槽的内容,可以使用 ::v-slotted()(简称 ::slotted())伪元素。

一次性的 Global 规则

目前,要添加一个全局性的 CSS 规则,我们需要使用一个单独的非范围(没有 scoped)的