【翻译】Vue RFCs 0001-new-slot-syntax

以下为原文翻译


综述

引入一个新的作用域插槽语法:

  • 新的指令v-slot使用同一个指令语法统一了slotslot-scope的语法。

  • v-slot的简化写法可以同时统一有作用域的插槽和普通插槽。

基本示例

使用v-slot来声明传入<foo>作用域插槽的属性。

<!-- 默认插槽 -->
<foo v-slot="{ msg }">
  {{ msg }}
</foo>

<!-- 命名插槽 -->
<foo>
  <template v-slot:one="{ msg }">
    {{ msg }}
  </template>
</foo>

动机

在我们最初引入作用域插槽时,代码因为总是需要使用 <template slot-scope>而变得十分啰嗦:

<foo>
  <template slot-scope="{ msg }">
    <div>{{ msg }}</div>
  </template>
</foo>

为了简化代码,在2.5中我们赋予了插槽元素直接使用slot-scope的能力:

<foo>
  <div slot-scope="{ msg }">
    {{ msg }}
  </div>
</foo>

同时也可以直接用在插槽组件上:

<foo>
  <bar slot-scope="{ msg }">
    {{ msg }}
  </bar>
</foo>

然而,上述的用法带来了一些问题:slot-scope的位置并不能总是明确地反应作用域变量来自哪个组件。比如slot-scope虽然声明在<bar>组件上,但它实际上定义了一个由<foo>的默认插槽提供的作用域变量。

这种情况随着嵌套加深愈来愈复杂:

<foo>
  <bar slot-scope="foo">
    <baz slot-scope="bar">
      <div slot-scope="baz">
        {{ foo }} {{ bar }} {{ baz }}
      </div>
    </baz>
  </bar>
</foo>

我们很难立即明确地指出,在这个模版中是哪个组件提供的变量。

有人建议我们应该允许把slot-scope直接声明在组件本身上以表示它的默认插槽范围:

<foo slot-scope="foo">
  {{ foo }}
</foo>

不幸的是,这种写法在嵌套组件出现时会有歧义:

<parent>
  <foo slot-scope="foo"> <!-- parent还是foo提供的? -->
    {{ foo }}
  </foo>
</parent>

这就是我认为在template之外使用slot-scope是个错误的原因。

为什么使用新的指令而不是修改slot-scope

如果时间可以倒流,我可能会改变slot-scope的语义,但:

  1. 现在这样做会导致breaking change,这意味着我们永远无法在2.x中使用这个特性。

  2. 即使我们在3.x中才改变已有语法的语义,在使用搜索引擎查询到过时的文档时,也会给未来的学习者带来非常多的问题。所以我们决定引入一个新的语法。

  3. 在3.x中,我们计划统一插槽类型使其不需要区分概念上的插槽和作用域插槽。一个插槽不论有没有属性都是插槽。随着概念的统一,就没有必要继续占用slotslot-scope两个特殊的属性了,并且在一个相同的结构下统一语法也是很好的选择。

细节设计

引入新指令: v-slot.

  • 他可以用在<template>插槽容器上代表插槽会传入组件,指令参数可以表示插槽的名字。

    <foo>
      <template v-slot:header>
        <div class="header"></div>
      </template>
    
      <template v-slot:body>
        <div class="body"></div>
      </template>
    
      <template v-slot:footer>
        <div class="footer"></div>
      </template>
    </foo>
    

    如果一个插槽是作用域插槽有属性,我们可以使用指令值来声明插槽属性。v-slot的值与slot-scope的值完全相同,所以支持JavaScript参数解构语法。

    <foo>
      <template v-slot:header="{ msg }">
        <div class="header">
          Message from header slot: {{ msg }}
        </div>
      </template>
    </foo>
    
  • 直接在组件上使用无参v-slot代表组件的默认插槽是一个作用域插槽,而传入插槽的属性应该和声明的属性相同。(翻译不通顺)

    <foo v-slot="{ msg }">
      {{ msg }}
    </foo>
    

新旧对比

让我们回顾一下这个提议是否能实现上文中的目标。

  • 仍然支持大部分用例下的简洁作用域插槽语法(只有默认插槽)

    <foo v-slot="{ msg }">{{ msg }}</foo>
    
  • 作用域变量与提供其之组件之间的关系更清晰:

    让我们再次观察上文中的深层嵌套例子,注意<foo>提供的作用域变量如何在<bar>上声明等等。

    <foo>
      <bar slot-scope="foo">
        <baz slot-scope="bar">
          <div slot-scope="baz">
            {{ foo }} {{ bar }} {{ baz }}
          </div>
        </baz>
      </bar>
    </foo>
    

这是新语法下的等价例子:

<foo v-slot="foo">
  <bar v-slot="bar">
    <baz v-slot="baz">
      {{ foo }} {{ bar }} {{ baz }}
    </baz>
  </bar>
</foo>

注意组件提供的作用域变量直接声明在组件自身上。新的语法使作用域变量与提供其之组件之间的关系更清晰。

更多用法比较

默认文本插槽

<!-- old -->
<foo>
  <template slot-scope="{ msg }">
    {{ msg }}
  </template>
</foo>

<!-- new -->
<foo v-slot="{ msg }">
  {{ msg }}
</foo>

默认元素插槽

<!-- old -->
<foo>
  <div slot-scope="{ msg }">
    {{ msg }}
  </div>
</foo>

<!-- new -->
<foo v-slot="{ msg }">
  <div>
    {{ msg }}
  </div>
</foo>

嵌套默认插槽

<!-- old -->
<foo>
  <bar slot-scope="foo">
    <baz slot-scope="bar">
      <template slot-scope="baz">
        {{ foo }} {{ bar }} {{ baz }}
      </template>
    </baz>
  </bar>
</foo>

<!-- new -->
<foo v-slot="foo">
  <bar v-slot="bar">
    <baz v-slot="baz">
      {{ foo }} {{ bar }} {{ baz }}
    </baz>
  </bar>
</foo>

命名插槽

<!-- old -->
<foo>
  <template slot="one" slot-scope="{ msg }">
    text slot: {{ msg }}
  </template>

  <div slot="two" slot-scope="{ msg }">
    element slot: {{ msg }}
  </div>
</foo>

<!-- new -->
<foo>
  <template v-slot:one="{ msg }">
    text slot: {{ msg }}
  </template>

  <template v-slot:two="{ msg }">
    <div>
      element slot: {{ msg }}
    </div>
  </template>
</foo>

命名插槽和默认插槽的混合嵌套用法

<!-- old -->
<foo>
  <bar slot="one" slot-scope="one">
    <div slot-scope="bar">
      {{ one }} {{ bar }}
    </div>
  </bar>

  <bar slot="two" slot-scope="two">
    <div slot-scope="bar">
      {{ two }} {{ bar }}
    </div>
  </bar>
</foo>

<!-- new -->
<foo>
  <template v-slot:one="one">
    <bar v-slot="bar">
      <div>{{ one }} {{ bar }}</div>
    </bar>
  </template>

  <template v-slot:two="two">
    <bar v-slot="bar">
      <div>{{ two }} {{ bar }}</div>
    </bar>
  </template>
</foo>

缺点

  • 引入新语法会使大量的学习资料过时,新用户可能在学习已有的教程后接触新语法时感到困惑。

    • 我们需要良好的文档说明语法的迁移。
  • 默认的用法中v-slot="{ msg }"并未明确的表达出msg应当作为参数传入插槽。

替代方案

采用策略

这个特性完全向后兼容,所以我们可以在一个小版本中推出它(计划在2.6中)(实际上已发布)

slot-scope会逐渐被废弃:首先它会在文档中标记为废弃,我们会鼓励所有人使用新语法,但是我们目前不会提示废弃消息,因为它在最新的语法迁移中并非最高优先级。

在3.0中我们确实希望移除slot-scope用法,并只支持新语法。我们会发出废弃slot-scope的信息以减轻迁移至3.0的压力。

由于这是一个良好定义的语法变化,我们可能提供一个自动化迁移工具来帮助你的模版文件进行迁移。


以上为原文翻译

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容