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

以下為原文翻譯


綜述

引入一個新的作用域插槽語法:

  • 新的指令v-slot使用同一個指令語法統(tǒng)一了slotslot-scope的語法。

  • v-slot的簡化寫法可以同時統(tǒng)一有作用域的插槽和普通插槽。

基本示例

使用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>

不幸的是,這種寫法在嵌套組件出現(xiàn)時會有歧義:

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

這就是我認為在template之外使用slot-scope是個錯誤的原因。

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

如果時間可以倒流,我可能會改變slot-scope的語義,但:

  1. 現(xiàn)在這樣做會導致breaking change,這意味著我們永遠無法在2.x中使用這個特性。

  2. 即使我們在3.x中才改變已有語法的語義,在使用搜索引擎查詢到過時的文檔時,也會給未來的學習者帶來非常多的問題。所以我們決定引入一個新的語法。

  3. 在3.x中,我們計劃統(tǒng)一插槽類型使其不需要區(qū)分概念上的插槽和作用域插槽。一個插槽不論有沒有屬性都是插槽。隨著概念的統(tǒng)一,就沒有必要繼續(xù)占用slotslot-scope兩個特殊的屬性了,并且在一個相同的結構下統(tǒng)一語法也是很好的選擇。

細節(jié)設計

引入新指令: v-slot.

  • 他可以用在<template>插槽容器上代表插槽會傳入組件,指令參數(shù)可以表示插槽的名字。

    <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參數(shù)解構語法。

    <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>
    

新舊對比

讓我們回顧一下這個提議是否能實現(xiàn)上文中的目標。

  • 仍然支持大部分用例下的簡潔作用域插槽語法(只有默認插槽)

    <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應當作為參數(shù)傳入插槽。

替代方案

采用策略

這個特性完全向后兼容,所以我們可以在一個小版本中推出它(計劃在2.6中)(實際上已發(fā)布)

slot-scope會逐漸被廢棄:首先它會在文檔中標記為廢棄,我們會鼓勵所有人使用新語法,但是我們目前不會提示廢棄消息,因為它在最新的語法遷移中并非最高優(yōu)先級。

在3.0中我們確實希望移除slot-scope用法,并只支持新語法。我們會發(fā)出廢棄slot-scope的信息以減輕遷移至3.0的壓力。

由于這是一個良好定義的語法變化,我們可能提供一個自動化遷移工具來幫助你的模版文件進行遷移。


以上為原文翻譯

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容