摘要

为 scoped slot 的使用引入了一种新语法:

  • 新的 v-slot 指令将 slot 和 slot-scope 统一到一个指令语法中。
  • v-slot 的简写有可能统一普通插槽和作用域插槽的使用。

基本范例

用 v-slot 来声明传递给 的作用域插槽:

  1. <!-- default slot -->
  2. <foo v-slot="{ msg }">
  3. {{ msg }}
  4. </foo>
  5. <!-- named slot -->
  6. <foo>
  7. <template v-slot:one="{ msg }">
  8. {{ msg }}
  9. </template>
  10. </foo>

动机

当我们第一次引入作用域插槽时,由于需要一直使用 <template slot-scope>,所以很啰嗦(verbose):

  1. <foo>
  2. <template slot-scope="{ msg }">
  3. <div>{{ msg }}</div>
  4. </template>
  5. </foo>

为了使它不那么冗长,在 2.5 中我们直接引入了在 slot 元素上使用 slot-scope 的能力:

  1. <foo>
  2. <div slot-scope="{ msg }">
  3. {{ msg }}
  4. </div>
  5. </foo>

这意味着它也可以直接组件上工作:

  1. <foo>
  2. <bar slot-scope="{ msg }">
  3. {{ msg }}
  4. </bar>
  5. </foo>

然而,在用法上就导致了一个问题:slot-scope 的位置并不是总能清除的反映出哪个组件实际的提供了作用域变量。这里的 slot-scope 被放在 bar 组件上,但它实际上是在定义一个由 <foo> 的默认插槽提供的作用域变量。

随着嵌套的加深,这种情况会越来越严重:

  1. <foo>
  2. <bar slot-scope="foo">
  3. <baz slot-scope="bar">
  4. <div slot-scope="baz">
  5. {{ foo }} {{ bar }} {{ baz }}
  6. </div>
  7. </baz>
  8. </bar>
  9. </foo>

在这个模版中,我们并不能立刻弄明白哪个组件提供了哪个变量。

有些人建议,我们应该允许在组件自己身上使用 slot-scope 来表示其默认插槽的作用域。

  1. <foo slot-scope="foo">
  2. {{ foo }}
  3. </foo>

不幸的是,这样的做法是行不通的,因为这样导致组件的嵌套很含糊。

  1. <parent>
  2. <foo slot-scope="foo"> <!-- provided by parent or by foo? -->
  3. {{ foo }}
  4. </foo>
  5. </parent>

这就是为什么我现在认为允许用没有模版的 slot-scope 是一个错误。

为什么是一个新的指令,而不是修复 slot-scope?

如果我们能回到过去,我可能会改变 slot-scope 的语义,但是:

  1. 这将是一个突破性的变化,这意味着我们将永远无法在 2.x 中发布它。
  2. 即使我们在 3.x 中改变了它,改变现有语法的语义也会给未来的学习者带来很多困惑,因为谷歌的学习资料已经过时。我们绝对(definitely)希望避免这种情况。所以,我们必须引入一些新东西来区别 slot-scope
  3. 在 3.x 中,我们计划统一 slot 类型,这样就不需要再区分作用域和非作用域插槽(概念上)。一个插槽可以接受也可以不接受 props,但他们都只是插槽。有了这种概念上的统一,slotslot-scope 这两个特殊的属性似乎没有必要了,而且把语法统一在一个结构下也会很好。

具体设计

引入一个新指令:v-slot

  • 它可以用在