摘要

rfc-0001 中提出的 v-slot 语法添加一个缩写语法。请先阅读 rfc-0001 文本,以获得该建议的背景知识。

基本范例

  1. <foo>
  2. <template #header="{ msg }">
  3. Message from header: {{ msg }}
  4. </template>
  5. <template #footer>
  6. A static footer
  7. </template>
  8. </foo>

动机

缩写,顾名思义,主要是为了提供更简洁的语法。

在 Vue 中,我们目前只为两个指令提供了缩写功能:v-bindv-on

  1. <div v-bind:id="id"></div>
  2. <div :id="id"></div>
  3. <button v-on:click="onClick"></button>
  4. <button @click="onClick"></button>

v-bindv-on 经常在同一个元素上重复使用,当每个元素之间的不同信息是指令参数而不是指令本身时,就会变得冗长。因此,通过缩短重复部分(v-xxx)和突出不同部分(参数),缩写有助于提高信噪比(信号/噪声)。

新的 v-slot 语法在组件中有多个插槽也会出现同样的问题:

  1. <TestComponent>
  2. <template v-slot:one="{ name }">Hello {{ name }}</template>
  3. <template v-slot:two="{ name }">Hello {{ name }}</template>
  4. <template v-slot:three="{ name }">Hello {{name }}</template>
  5. </TestComponent>

这里 v-slot 重复了多次,其中实际不同的部分是插槽名(用参数表示)。

这种缩写方法有助于将插槽名称更容易被扫描。

  1. <TestComponent>
  2. <template #one="{ name }">Hello {{ name }}</template>
  3. <template #two="{ name }">Hello {{ name }}</template>
  4. <template #three="{ name }">Hello {{name }}</template>
  5. </TestComponent>

具体设计

缩写方法与 v-bindv-on 的缩写规则非常相似:用缩写符号(#)替换指令名和冒号:

  1. <!-- full syntax -->
  2. <foo>
  3. <template v-slot:header="{ msg }">
  4. Message from header: {{ msg }}
  5. </template>
  6. <template v-slot:footer>
  7. A static footer
  8. </template>
  9. </foo>
  10. <!-- shorthand -->
  11. <foo>
  12. <template #header="{ msg }">
  13. Message from header: {{ msg }}
  14. </template>
  15. <template #footer>
  16. A static footer
  17. </template>
  18. </foo>

v-bindv-on 类似,这种缩写法只在有参数的情况下有效。这意味着没有参数的 v-slot 不能简化为 #=。对于默认插槽,应该使用完整的语法(v-slot)或者明确的名称(#default)。

  1. <foo v-slot="{ msg }">
  2. {{ msg }}
  3. </foo>
  4. <foo #default="{ msg }">
  5. {{ msg }}
  6. </foo>

对 # 的选择是基于之前 RFC 中收集的反馈。它与 CSS 中的 ID 选择器有相似之处,并且在概念上很好的转化为插槽的名称。

在一个依赖作用域插槽的真实世界的库中的一些使用案例:

  1. <Promised :promise="usersPromise">
  2. <template #pending>
  3. <p>Loading...</p>
  4. </template>
  5. <template #default="users">
  6. <ul>
  7. <li v-for="user in users">{{ user.name }}</li>
  8. </ul>
  9. </template>
  10. <template #rejected="error">
  11. <p>Error: {{ error.message }}</p>
  12. </template>
  13. </Promised>

缺点

  • 有些人会说,slot 不是那么常用,因此并不是真正需要缩写,而且可能导致初学者的学习曲线增高。对此,我的答案是:

    1. 我相信作用域插槽是建立高度可定制和可组合的第三方组件套件的一个重要机制。我认为我们在未来会看到更多使用组件库依靠插槽来进行定制和组合。对于使用这种组件库的用户来说,缩写将变得相当有价值(正如例子中所展示的)。
    2. 缩写的转换规则很直接,与现有的缩写法一致。如果用户学会了基本语法的工作方式,那么理解缩写就是一个成本非常小的步骤。

      备选方案

      在以前讨论的 RFC 中已经提出并讨论了一些替代符号。唯一一个类似的有意义的是 &。

      1. <foo>
      2. <template &header="{ msg }">
      3. Message from header: {{ msg }}
      4. </template>
      5. <template &footer>
      6. A static footer
      7. </template>
      8. </foo>

采纳策略

这应该是在新的 v-slot 的语法之上的自然扩展。理想情况下,我们希望同时引入基础语法和缩写的语法,这样用户就可以同时学习这两种语法。之后再引入缩写语法,会有用户只知道 v-slot 语法的风险,当在别人的代码中看到缩写时就会感到困惑。

没有解决的问题

N/A