Vue插槽學習理解

閱讀之前

本文主要參照了Vue官方文檔的插槽部分說明,中間加入的自己的理解,寫的比較簡潔易懂。各位看官可以對照官方文檔和本文的介紹來理解slot插槽語法。

Vue 插槽(2.60版本以后)

插槽可以讓通用組件更加多樣化,它類似React中的children。

聲明:以下所有內(nèi)容以父級(通用)組件和應(yīng)用(調(diào)用)組件的關(guān)系舉例說明。

  • 最簡單的使用

比如你想聲明一個帶有特殊border的div作為一個通用組件BorderedDiv。

<template>
  <div class="some-border-class">
    // 這里是包裹的不同的內(nèi)容
    // 可能你很想使用this.props.children(如果你曾是React使用者)
  </div>
</template>

在使用該組件時

<bordered-div>
  <p>被包裹的文字</p>
</bordered-div>

這時你會想到:這個文字如何傳遞給父級組件呢?

直接這樣寫就好:

<template>
  <div class="some-border-class">
    // 這里是包裹的不同的內(nèi)容
    <slot></slot>
  </div>
</template>
  • 作用域

<common-component :data="[1,2,3]">
    {{ data }}
    <!-- 
    這里的 `data` 會是 undefined,因為數(shù)組是 **傳遞給**  
    <common-component> 的而不是 在 <common-component> 組件
    **內(nèi)部**定義的
    -->
</common-component >

父級模板里的所有內(nèi)容都是在父級作用域中編譯的;子模板里的所有內(nèi)容都是在子作用域中編譯的。

簡單來說:你不能在寫children的時候直接使用父級組件中的數(shù)據(jù),考慮當前環(huán)境。

  • 后備內(nèi)容

在<slot></slot>標簽中的內(nèi)容將在沒有匹配到插槽內(nèi)容時渲染

 <slot>如果沒有children,我就會渲染</slot>

如果父級模板中聲明了插槽,但是應(yīng)用組件卻沒有包裹任何內(nèi)容,它便會渲染為備用內(nèi)容。

  • 具名

可以給<slot></slot> 傳遞name屬性

<div class="container">
<header>
    <slot name="header"></slot>
</header>
<main>
    <slot name="default"></slot>
</main>
<footer>
    <slot name="footer"></slot>
</footer>
</div>

然后這樣向?qū)?yīng)的插槽傳遞內(nèi)容:

<base-layout>
    <template v-slot:header>
        <h1>Here might be a page title</h1>
    </template>
    // 可以不用包裹template 直接傳遞給default slot
    <template v-slot:default>
        <p>A paragraph for the main content.</p> 
        <p>And another one.</p>
    </template>
    
    <template v-slot:footer>
        <p>Here's some contact info</p>
    </template>
</base-layout>

其中:<template v-slot:default>父節(jié)點可以省略。

注意:

v-slot指令只能使用在<template>上,除非只需要傳遞默認插槽。(也就是你的父級模板中只有一個沒有name屬性的插槽)
這時它可以用在父組件上。
盡管如此,它也只是<template v-slot:default></template>的縮寫。
在傳遞多個插槽時,還是需要使用完整的語法。

  • 作用域插槽

在通用組件中聲明的模板如下:

<span>
    // 給slot聲明了一個屬性 
    // 該屬性可以在對應(yīng)的插槽內(nèi)容中訪問
    // 省略了 name = "default"
    <slot v-bind:user="user"></slot>
</span>

在應(yīng)用組件中:

<common-component>
    <!-- v-slot是v-slot:default的縮寫 -->
    <template v-slot="slotProps">
        // 插槽上聲明的user可以這樣訪問
        {{ slotProps.user.name }}
    </template>
</common-component>

在“裝載插槽”時,slot上聲明的屬性綁定的數(shù)據(jù)會以函數(shù)的參數(shù)形式傳遞給插槽

function (slotProps) {
    // 插槽的內(nèi)容
}

因此可以在編寫插槽內(nèi)容時獲取到common-component(父組件)中的數(shù)據(jù)。

由于slotProps是以函數(shù)參數(shù)的形式傳遞的,因此各種簡寫也就可以理解了。

    // 解構(gòu)傳參
    <template v-slot:default="{ user }">
        {{  user.name }}
    </template>
    // 重命名
    <template v-slot:default="{ user: person }" >
        {{ person.name }}
    </template>
    // 默認值
    <template v-slot:default="{ user={ firstname: 'test' } }">
        {{ user.name }}
    </template>
  • 縮寫

在向具名(聲明了name屬性的)插槽傳遞內(nèi)容時,(應(yīng)用組件中)可以使用縮寫:

<common-layout>
    // 等同于:v-slot:header
   <template #header>
   // 以下模板內(nèi)容會傳遞給name = header的插槽
       <p>this is header</p>
   </template>
   // 注意: 不可以 直接#
   <template #default>
   // 以下內(nèi)容會傳遞給沒有聲明name的插槽,也就是默認插槽
       <p>this is default slot</p>
   </template>
</common-layout>

當然如果common-layout模板中如果只有一個默認插槽的話,你可以直接這樣做:

// 相當于: v-slot:default="slotProps"
// default不可省略,否則引發(fā)警告
<common-layout #default="slotProps">
   {{ slotProps.user.name }}
</common-layout>
  • 其他示例

請先看官方給出的示例:todoList示例

關(guān)鍵點:
通用組件中這樣聲明:

<!--
    我們?yōu)槊總€ todo 準備了一個插槽, 將 `todo` 對象作為一個
    插槽的 prop 傳入.
-->
    <slot name="todo" v-bind:todo="todo">
        <!-- 后備內(nèi)容 -->
        {{ todo.text }}
    </slot>

應(yīng)用組件中這樣使用:

<todo-list v-bind:todos="todos">
    // 或者簡寫為: #todo
    <template v-slot:todo="{ todo }">
        <span v-if="todo.isComplete">?</span>
        {{ todo.text }}
    </template>
</todo-list>

這樣使用就將li中的內(nèi)容動態(tài)化。

  • 理解

slot的基本用法簡單來說就是(我的理解):

在你聲明一個通用的組件時,將通用的部分聲明為模板,動態(tài)的內(nèi)容,也就是各個應(yīng)用組件不一致的地方,或者說可能需要動態(tài)渲染的部分聲明為插槽slot,并給該插槽定義name,prop,以方便應(yīng)用組件獲取數(shù)據(jù)和對號入座。

參考:

Vue官方文檔: https://cn.vuejs.org/v2/guide/components-slots.html

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容