天天看點

Vue | 15 元件深入-插槽

内容提要:
  1. 插槽的内容
  2. 命名的插槽
  3. 預設插槽内容
  4. 插槽的編譯範圍
  5. 作用域插槽
  6. 解構

    slot-scope

這頁假定你已經閱讀元件基礎( Components Basics),如果你不了解元件,請先閱讀它。

插槽内容

Vue實作了一套内容分發的API。該API基于目前Web元件規範草案 Web Components spec draft。使用slot元素去作為内容分發的出口。

這允許你去像這樣組成元件:

<navigation-link url="/profile">
    Your Profile
</navigation-link>
           

然後,在navigaiton-link标簽的模闆中,你可以有:

<a
   v-bind:href="url" target="_blank" rel="external nofollow" 
   class="nav-link">
    <slot></slot>
</a>
           

當元件渲染的時候,slot标簽元素将被“Your Profile”替換,Slots能包含任何模闆代碼,包括HTML:

<navigation-link url="/profile">
    <!-- Add a Font Awesome icon -->
    <span class="fa fa-user"></span>
    Your Profile
</navigation-link>
           

或者甚至其他元件:

<navigation-link url="/profile">
    <!-- 使用元件去增加一個圖示 -->
    <font-awesome-icon name="user"></font-awesome-icon>
    Your Profile
</navigation-link>
           

如果navigation-link元素不包含slot标簽元素,任何傳遞給它的内容僅僅會被丢棄。

被指名的插槽

有時候我們需要多個插槽,例如,假設base-layout元件使用以下模闆:

<div class="container">
    <header>
        <!-- header内容 -->
    </header>
    <main>
        <!-- main内容 -->
    </main>
    <footer>
        <!-- footer内容 -->
    </footer>
</div>
           

對于這些事例,slot标簽元素有一個特定屬性,

name

可用于定義額外插槽:

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

去提供内容給被命名的slots,我們能夠使用template标簽元素的

slot

屬性在父節點。

<base-layout>
    <template slot="header">
        <h1>這可能是一個頁的标題</h1>
    </template>
    
    <p>段落主要内容</p>
    <p>另一段</p>
    
    <template solt="footer">
        <p>這有一些聯系人資訊</p>
    </template>
</base-layout>
           

或,

slot

屬性能被直接的用在一個正常的元素:

<base-layout>
    <h1 slot="header">這可能是本頁的标題</h1>
    
    <p>這段的主要内容</p>
    <p>另一段</p>
    
    <p slot="footer">這是一些聯資訊</p>
</base-layout>
           

仍然可能有一個未命名的插槽,這是一個預設插槽,用于為不比對的内容提供通配符輸出。在以上這些例子,HTML将被渲染:

<div class="container">
    <header>
        <h1>這可能是一個标題</h1>
    </header>
    <main>
        <p>一段主要内容</p>
        <p>另一段</p>
    </main>
    <footer>
        <p>這是一些聯系資訊</p>
    </footer>
</div>
           

預設插槽内容

在一些情況下,提供一個預設内容的插槽可能是有用的。例如,一個submit-button元素元件可能需要預設的Submit的按鈕内容,但是也允許用于用“Save”,“Upload”,或其他任何内容複寫。

為了實作這個,在你的元件模闆的标簽之間指定預設内容:

<butotn type="submit">
    <slot>Submit</slot>
</butotn>
           

如果插槽通過父節點提供了内容,它将會替換預設内容。

編譯範圍

當你想在一個插槽内使用資料的時候,像這樣:

<navigaiton-link url="/profile">
    Logged in as {{ user.name }}
</navigaiton-link>
           

插槽可以通路和模闆的清湯地方相同的執行個體屬性(即“作用域”相同)。插槽不能夠通路navigaiton-link标簽的作用域,例如,試着去通路url将沒辦法工作,作為一個規則,記住:

在父模闆的每一件事情在父作用域編譯,在子模闆的每一件事情在子作用域編譯。

插槽作用域

在 2.1.0新增

有時你可能想要提供一個元件帶有一個能從子元件通路資料的可複用的插槽。例如,一個簡單的todo-list元素元件可能包含以下模闆:

<ul>
    <li
        v-for="todo in todos"
        v-bind:key="todo.id">
    </li>
    {{ todo.text }}
</ul>
           

但是在我們app的某些部分,我們想要一些特别的操作項去渲染不用于

todo.text

的内容。這就是作用域卡槽帶來的作用。

為了使這個功能成為可能,我們不得不在一個元素封裝所有todo 清單内容,然後傳遞給slot任何相關的内容資料: 在這個例子中,使用

todo

對象:

<ul>
    <li
        v-for="todo in todos"
        v-bind:key="todo.id">
        <!-- 我們為每一個插槽建立一個todo,傳遞給它‘todo’對象作為一個slot prop -->
        <slot v-bind:todo="todo">
            <!-- 回退的内容 -->
            {{ todo.text }}
    </li>
</ul>
           

現在當我們使用todo-list元素元件的時候,我們可以選擇為待辦事項選擇一個替代方案template元素,但是從子元件的

slot-scope

屬性通路資料:

<todo-list v-bind:todos="todos">
    <!-- 定義一個'slotProps'作為我們slot作業域的名字 -->
    <template slot-scope="slotProps">
        <!-- 為todo items 定義一個自定義模闆,使用`slotProps`to自定義每一個todo -->
        <span v-if="slotProps.todo.isComplete"></span>
        {{ slotProps.todo.text }}
    </template>
</todo-list>
           
在2.5.0+,

slot-scope

不再被 元素限制,而是能夠替代使用在slot的任何元件或元素。

解構slot-scope

slot-scope的值實際上能接受任何出現在函數定義的參數位置的JavaScript表達式。意思是說在支援的環境下(single-file components or modern browsers)你能夠在表達式中使用 ES2015 destructuring 解構文法,例如:

<todo-list v-bind:todos="todos">
    <template slot-scope="{ todo }">
        <span v-if="todo.isComplete">✓</span>
        {{ todo.text }}
    </template>
</todo-list>
           

這會使作用域插槽更幹淨一些。

繼續閱讀