Vue理解插槽及其slot、slot-scope、v-slot指令的使用

什麼是插槽

Vue本身實現了一套完善的內容分發的機制,使用<slot>元素作爲內容分發的出口,也就是插槽。插槽內的模板<template>、HTML代碼以及組件會被渲染。

<!-- Example組件的定義 -->
<h1>
  <slot></slot>
</h1>

<Child>
  <p>我是插槽內容</p>
</Child>

如果組件本身沒有<slot>元素作爲出口,那麼組件包含的內容都會被捨棄

<!-- Example組件的定義 -->
<h1></h1>

<Child>
  <!-- 被捨棄,不渲染 -->
  <p>我是插槽內容</p>
</Child>

默認插槽/匿名插槽(default slot)

上面例子中的<slot>沒有顯式聲明name屬性,就是默認插槽,其name的屬性值默認爲‘default’。如果向插槽傳入數據時沒有指明插槽名,就會傳入默認插槽

具名插槽

具名插槽就是帶有name屬性的<slot>。在很多情況下,需要向多個插槽傳入內容,此時就需要用到具名插槽。

作用域插槽

有時父組件需要訪問插槽裏的作用域,此時可以通過作用域插槽(v-slot和slot-scope)訪問插槽的作用域對象,它由插槽上定義的特性值組成。

插槽默認值(後備內容)

<!-- Example組件的定義 -->
<h1>
  <slot>我是默認值</slot>
</h1>

<!-- 會渲染成<h1>我是默認值</h1> -->
<Child>
</Child>

<!-- 會渲染成<h1><p>我是新內容</p></h1> -->
<Child>
  <p>我是新內容</p>
</Child>

slot和slot-scope(3.0版本之後移除),可以通過vue-V查看vue版本

slot用於綁定傳入內容的插槽,slot-scope獲取插槽的作用域對象

v-slot(2.6版本之後加入)

結合上述兩個指令的新指令:

  • v-slot:slotName綁定傳入的插槽,縮寫爲#slotName 等價於slot=“slotName”
  • v-slot:slotName=“scope”,獲取插槽的作用域對象並賦值給scope,等價於slot-scope=“scope”。同時可以使用ES6的解構語法獲取指定的特性v-slot="{ footer }"
  • 當插槽爲默認插槽時,v-slot可以不帶修飾符,直接在組件上使用,並且將默認插槽的作用域賦給v-slot聲明的變量
  • 最重要的一個特性就是可以直接在組件上聲明獲取插槽組件的作用域對象

slot-scope與v-slot的新老指令的使用對比

1. 默認文本插槽

<!-- 默認文本插槽 -->
<!-- old -->
<foo>
  <template slot-scope="{ msg }">
    {{ msg }}
  </template>
</foo>

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

2. 默認元素插槽

<!-- 默認元素插槽 -->
<!-- old -->
<foo>
  <div slot-scope="{ msg }">
    {{ msg }}
  </div>
</foo>

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

3. 嵌套默認插槽

<!-- 嵌套默認插槽 -->
<!-- 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>

4. 具名插槽

<!-- 具名插槽 -->
<!-- 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>

5. 具名與默認混合嵌套插槽

<!-- 具名與默認混合嵌套插槽 -->
<!-- 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>

參考

  1. RFCs
  2. Vue.js-Slots(English)
  3. Vue.js-插槽(中文)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章