亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

插槽

插槽:簡單理解就是組件內(nèi)部留一個(gè)或多個(gè)的插槽位置,可供組件傳對應(yīng)的模板代碼進(jìn)去。插槽的出現(xiàn),讓組件變的更加靈活。


該頁面假設(shè)你已經(jīng)閱讀過了組件基礎(chǔ)。如果你還對組件不太了解,推薦你先閱讀它。

在 2.6.0 中,我們?yōu)榫呙宀酆妥饔糜虿宀垡肓艘粋€(gè)新的統(tǒng)一的語法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 這兩個(gè)目前已被廢棄但未被移除且仍在文檔中的特性。新語法的由來可查閱這份 RFC。


目錄



插槽內(nèi)容


Vue 實(shí)現(xiàn)了一套內(nèi)容分發(fā)的 API,這套 API 的設(shè)計(jì)靈感源自 Web Components 規(guī)范草案,將 <slot> 元素作為承載分發(fā)內(nèi)容的出口。

它允許你像這樣合成組件:

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

然后你在 <navigation-link> 的模板中可能會寫為:

<a
  v-bind:href="url"
  class="nav-link"
>
  <slot></slot>
</a>

當(dāng)組件渲染的時(shí)候,<slot></slot> 將會被替換為“Your Profile”。插槽內(nèi)可以包含任何模板代碼,包括 HTML:

<navigation-link url="/profile">
  <!-- 添加一個(gè) Font Awesome 圖標(biāo) -->
  <span class="fa fa-user"></span>
  Your Profile
</navigation-link>

甚至其它的組件:

<navigation-link url="/profile">
  <!-- 添加一個(gè)圖標(biāo)的組件 -->
  <font-awesome-icon name="user"></font-awesome-icon>
  Your Profile
</navigation-link>

如果 <navigation-link> 沒有包含一個(gè) <slot> 元素,則該組件起始標(biāo)簽和結(jié)束標(biāo)簽之間的任何內(nèi)容都會被拋棄。


編譯作用域


當(dāng)你想在一個(gè)插槽中使用數(shù)據(jù)時(shí),例如:

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

該插槽跟模板的其它地方一樣可以訪問相同的實(shí)例屬性 (也就是相同的“作用域”),而不能訪問 <navigation-link> 的作用域。例如 url 是訪問不到的:

<navigation-link url="/profile">
  Clicking here will send you to: {{ url }}
  <!--
  這里的 `url` 會是 undefined,因?yàn)?nbsp;"/profile" 是
  _傳遞給_ <navigation-link> 的而不是
  在 <navigation-link> 組件*內(nèi)部*定義的。
  -->
</navigation-link>

作為一條規(guī)則,請記?。?/p>

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


后備內(nèi)容


有時(shí)為一個(gè)插槽設(shè)置具體的后備 (也就是默認(rèn)的) 內(nèi)容是很有用的,它只會在沒有提供內(nèi)容的時(shí)候被渲染。例如在一個(gè) <submit-button> 組件中:

<button type="submit">
  <slot></slot>
</button>

我們可能希望這個(gè) <button> 內(nèi)絕大多數(shù)情況下都渲染文本“Submit”。為了將“Submit”作為后備內(nèi)容,我們可以將它放在 <slot> 標(biāo)簽內(nèi):

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

現(xiàn)在當(dāng)我在一個(gè)父級組件中使用 <submit-button> 并且不提供任何插槽內(nèi)容時(shí):

<submit-button></submit-button>

后備內(nèi)容“Submit”將會被渲染:

<button type="submit">
  Submit
</button>

但是如果我們提供內(nèi)容:

<submit-button>
  Save
</submit-button>

則這個(gè)提供的內(nèi)容將會被渲染從而取代后備內(nèi)容:

<button type="submit">
  Save
</button>


具名插槽


自 2.6.0 起有所更新。已廢棄的使用 slot 特性的語法在這里。

有時(shí)我們需要多個(gè)插槽。例如對于一個(gè)帶有如下模板的 <base-layout> 組件:

<div class="container">
  <header>
    <!-- 我們希望把頁頭放這里 -->
  </header>
  <main>
    <!-- 我們希望把主要內(nèi)容放這里 -->
  </main>
  <footer>
    <!-- 我們希望把頁腳放這里 -->
  </footer>
</div>

對于這樣的情況,<slot> 元素有一個(gè)特殊的特性:name。這個(gè)特性可以用來定義額外的插槽:

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

一個(gè)不帶 name<slot> 出口會帶有隱含的名字“default”。

在向具名插槽提供內(nèi)容的時(shí)候,我們可以在一個(gè) <template> 元素上使用 v-slot 指令,并以 v-slot 的參數(shù)的形式提供其名稱:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

現(xiàn)在 <template> 元素中的所有內(nèi)容都將會被傳入相應(yīng)的插槽。任何沒有被包裹在帶有 v-slot<template> 中的內(nèi)容都會被視為默認(rèn)插槽的內(nèi)容。

然而,如果你希望更明確一些,仍然可以在一個(gè) <template> 中包裹默認(rèn)插槽的內(nèi)容:

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <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>

任何一種寫法都會渲染出:

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

注意: v-slot 只能添加在一個(gè) <template> 上 (只有一種例外情況),這一點(diǎn)和已經(jīng)廢棄的 slot 特性不同。


作用域插槽


自 2.6.0 起有所更新。已廢棄的使用 slot-scope 特性的語法在這里。

有時(shí)讓插槽內(nèi)容能夠訪問子組件中才有的數(shù)據(jù)是很有用的。例如,設(shè)想一個(gè)帶有如下模板的 <current-user> 組件:

<span>
  <slot>{{ user.lastName }}</slot>
</span>

我們想讓它的后備內(nèi)容顯示用戶的名,以取代正常情況下用戶的姓,如下:

<current-user>
  {{ user.firstName }}
</current-user>

然而上述代碼不會正常工作,因?yàn)橹挥?<current-user> 組件可以訪問到 user 而我們提供的內(nèi)容是在父級渲染的。

為了讓 user 在父級的插槽內(nèi)容中可用,我們可以將 user 作為 <slot> 元素的一個(gè)特性綁定上去:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

綁定在 <slot> 元素上的特性被稱為插槽 prop?,F(xiàn)在在父級作用域中,我們可以給 v-slot 帶一個(gè)值來定義我們提供的插槽 prop 的名字:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

在這個(gè)例子中,我們選擇將包含所有插槽 prop 的對象命名為 slotProps,但你也可以使用任意你喜歡的名字。


獨(dú)占默認(rèn)插槽的縮寫語法

在上述情況下,當(dāng)被提供的內(nèi)容只有默認(rèn)插槽時(shí),組件的標(biāo)簽才可以被當(dāng)作插槽的模板來使用。這樣我們就可以把 v-slot 直接用在組件上:

<current-user v-slot:default="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

這種寫法還可以更簡單。就像假定未指明的內(nèi)容對應(yīng)默認(rèn)插槽一樣,不帶參數(shù)的 v-slot 被假定對應(yīng)默認(rèn)插槽:

<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
</current-user>

注意默認(rèn)插槽的縮寫語法不能和具名插槽混用,因?yàn)樗鼤?dǎo)致作用域不明確:

<!-- 無效,會導(dǎo)致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

只要出現(xiàn)多個(gè)插槽,請始終為所有的插槽使用完整的基于 <template> 的語法:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>


解構(gòu)插槽 Prop

作用域插槽的內(nèi)部工作原理是將你的插槽內(nèi)容包括在一個(gè)傳入單個(gè)參數(shù)的函數(shù)里:

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

這意味著 v-slot 的值實(shí)際上可以是任何能夠作為函數(shù)定義中的參數(shù)的 JavaScript 表達(dá)式。所以在支持的環(huán)境下 (單文件組件現(xiàn)代瀏覽器),你也可以使用 ES2015 解構(gòu)來傳入具體的插槽 prop,如下:

<current-user v-slot="{ user }">
  {{ user.firstName }}
</current-user>

這樣可以使模板更簡潔,尤其是在該插槽提供了多個(gè) prop 的時(shí)候。它同樣開啟了 prop 重命名等其它可能,例如將 user 重命名為 person

<current-user v-slot="{ user: person }">
  {{ person.firstName }}
</current-user>

你甚至可以定義后備內(nèi)容,用于插槽 prop 是 undefined 的情形:

<current-user v-slot="{ user = { firstName: 'Guest' } }">
  {{ user.firstName }}
</current-user>


動(dòng)態(tài)插槽名


2.6.0 新增

動(dòng)態(tài)指令參數(shù)也可以用在 v-slot 上,來定義動(dòng)態(tài)的插槽名:

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>


具名插槽的縮寫


2.6.0 新增

v-onv-bind 一樣,v-slot 也有縮寫,即把參數(shù)之前的所有內(nèi)容 (v-slot:) 替換為字符 #。例如 v-slot:header 可以被重寫為 #header

<base-layout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <template #footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

然而,和其它指令一樣,該縮寫只在其有參數(shù)的時(shí)候才可用。這意味著以下語法是無效的:

<!-- 這樣會觸發(fā)一個(gè)警告 -->
<current-user #="{ user }">
  {{ user.firstName }}
</current-user>

如果你希望使用縮寫的話,你必須始終以明確插槽名取而代之:

<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>


其它示例


插槽 prop 允許我們將插槽轉(zhuǎn)換為可復(fù)用的模板,這些模板可以基于輸入的 prop 渲染出不同的內(nèi)容。這在設(shè)計(jì)封裝數(shù)據(jù)邏輯同時(shí)允許父級組件自定義部分布局的可復(fù)用組件時(shí)是最有用的。

例如,我們要實(shí)現(xiàn)一個(gè) <todo-list> 組件,它是一個(gè)列表且包含布局和過濾邏輯:

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

我們可以將每個(gè) todo 作為父級組件的插槽,以此通過父級組件對其進(jìn)行控制,然后將 todo 作為一個(gè)插槽 prop 進(jìn)行綁定:

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

現(xiàn)在當(dāng)我們使用 <todo-list> 組件的時(shí)候,我們可以選擇為 todo 定義一個(gè)不一樣的 <template> 作為替代方案,并且可以從子組件獲取數(shù)據(jù):

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

這只是作用域插槽用武之地的冰山一角。想了解更多現(xiàn)實(shí)生活中的作用域插槽的用法,我們推薦瀏覽諸如 Vue Virtual Scroller、Vue PromisedPortal Vue 等庫。


廢棄了的語法


v-slot 指令自 Vue 2.6.0 起被引入,提供更好的支持 slot 和 slot-scope 特性的 API 替代方案。v-slot 完整的由來參見這份 RFC。在接下來所有的 2.x 版本中 slot 和 slot-scope 特性仍會被支持,但已經(jīng)被官方廢棄且不會出現(xiàn)在 Vue 3 中。


帶有 slot 特性的具名插槽

自 2.6.0 起被廢棄。新推薦的語法請查閱這里。

<template> 上使用特殊的 slot 特性,可以將內(nèi)容從父級傳給具名插槽 (把這里提到過的 <base-layout> 組件作為示例):

<base-layout>
  <template slot="header">
    <h1>Here might be a page title</h1>
  </template>
  
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  
  <template slot="footer">
    <p>Here's some contact info</p>
  </template>
</base-layout>

或者直接把 slot 特性用在一個(gè)普通元素上:

<base-layout>
  <h1 slot="header">Here might be a page title</h1>
  
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  
  <p slot="footer">Here's some contact info</p>
</base-layout>

這里其實(shí)還有一個(gè)未命名插槽,也就是默認(rèn)插槽,捕獲所有未被匹配的內(nèi)容。上述兩個(gè)示例的 HTML 渲染結(jié)果均為:

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>


帶有 slot-scope 特性的作用域插槽

自 2.6.0 起被廢棄。新推薦的語法請查閱這里。

<template> 上使用特殊的 slot-scope 特性,可以接收傳遞給插槽的 prop (把這里提到過的 <slot-example> 組件作為示例):

<slot-example>
  <template slot="default" slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

這里的 slot-scope 聲明了被接收的 prop 對象會作為 slotProps 變量存在于 <template> 作用域中。你可以像命名 JavaScript 函數(shù)參數(shù)一樣隨意命名 slotProps。

這里的 slot="default" 可以被忽略為隱性寫法:

<slot-example>
  <template slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

slot-scope 特性也可以直接用于非 <template> 元素 (包括組件):

<slot-example>
  <span slot-scope="slotProps">
    {{ slotProps.msg }}
  </span>
</slot-example>

slot-scope 的值可以接收任何有效的可以出現(xiàn)在函數(shù)定義的參數(shù)位置上的 JavaScript 表達(dá)式。這意味著在支持的環(huán)境下 (單文件組件現(xiàn)代瀏覽器),你也可以在表達(dá)式中使用 ES2015 解構(gòu),如下:

<slot-example>
  <span slot-scope="{ msg }">
    {{ msg }}
  </span>
</slot-example>

使用這里描述過的 <todo-list> 作為示例,與它等價(jià)的使用 slot-scope 的代碼是:

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