v-solt 插槽(基礎使用、具名插槽、作用域插槽等)

2021-04-13 15:01:02

基本使用

元件通過slot預留位置,使用元件的時候,可以通過傳遞具體的內容去替換slot佔用的地方,這就是插槽。

比如現在定義了一個元件:

<!--
simple-use.vue
-->
<template>
  <div>
    <slot></slot>
  </div>
</template>

元件<slot></slot>佔用的位置具體內容不確定,需要使用的時候傳遞進來,我們就可以這樣使用:

<simple-use>
  <em style='color:red'>傳遞給插槽的內容(可以是文字,標籤或者元件等)</em>
</simple-use>

最終的結果可以理解為:

<template>
  <div>
    <!-- <slot></slot> 這個標記的內容被下面的代替了 -->
    <em style='color:red'>傳遞給插槽的內容(可以是文字,標籤或者元件等)</em>
  </div>
</template>

給插槽一個預設值

有時候,我們可能希望slot有一個自己的預設值,在沒有傳遞資料給元件的時候,使用預設資料。
想實現這樣給功能很簡單,只要在slot直接新增預設值即可,比如:

<!--
default-content.vue
-->
<template>
  <div>
    <slot>
      沒有傳遞資料時候的預設值
    </slot>
  </div>
</template>

使用的時候就可以傳遞或者不傳遞資料:

<default-content></default-content>
<default-content>這是傳遞的資料</default-content>

最終的結果可以理解為:

<template>
  <div>
      沒有傳遞資料時候的預設值
  </div>
</template>

<template>
  <div>
    這是傳遞的資料
  </div>
</template>

我們看見,第一個選擇了預設資料,第二個使用了傳遞進去的資料。

溫馨提示:父級模板裡面的所有內容都是在父級作用域中編譯的,子模板裡面的所有內容都是在子作用域中編譯的。

具名插槽

有時候slot可能有多個,為了對應起來,可以給slot起名字,傳遞的時候對應起來:

<!--
name-slot.vue
-->
<template>
  <ul>
    <li>
      <slot name='index1'></slot>
    </li>
    <li>
      <slot name='index2'></slot>
    </li>
    <li>
      <slot></slot>
    </li>
  </ul>
</template>

我們定義了三個slot,其中二個名字分別叫index1和index2,第三個沒有定義名稱,預設名稱是default,因此,我們在使用的時候就需要這樣使用:

<name-slot>
  <template v-slot:index1>
    地方1
  </template>
  <template v-slot:index2>
    地方2
  </template>
  <template v-slot:default>
    預設地方
  </template>
</name-slot>

我們通過v-slot:name的方式把template模板和slot對應了起來,因此執行後的結果就是:

<!--
name-slot.vue
-->
<template>
  <ul>
    <li>
      地方1
    </li>
    <li>
      地方2
    </li>
    <li>
      預設地方
    </li>
  </ul>
</template>
需要注意的是,v-slot只能新增在<template>上(不過"作用域插槽"這種情況除外)。

作用域插槽

有時候我們希望在使用元件的是,讓插槽內容存取子元件中的資料,可以通過插槽 prop這個特性實現:

<!--
scope-slot.vue
-->
<template>
  <div>
    <slot v-bind:message='message'></slot>
  </div>
</template>
<script>
export default {
  data() {
    return {
      message: "來自子元件中的資料"
    };
  }
};
</script>

使用的時候,我們需要接收一下:

<scope-slot>
  <!-- 這裡的default表示預設的,如果有多個插槽,改為對應的插槽名字 -->
  <template v-slot:default='sub_scope'>
    {{sub_scope.message}}
  </template>
</scope-slot>

最終的結果就是:

<template>
  <div>
    來自子元件中的資料
  </div>
</template>