VUE v-slot插槽


具名插槽

在 2.6.0+ 中已棄用

先前,我們使用具名插槽來自定義模板內容,例如,一個假設的 <base-layout> 組件的模板如下:

<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> 復制代碼

在向具名插槽提供內容的時候,我們可以在一個父組件的 <template> 元素上使用 slot 特性:

<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> 復制代碼

或者直接用在一個普通的元素上:

<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> 復制代碼

上述兩個示例渲染出來的 HTML 都將會是:

<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 指令改寫上面的栗子:

<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> 復制代碼

就是這么簡單,插槽的名字現在通過 v-slot:slotName 這種形式來使用。

Tips: 沒有名字的 <slot> 隱含有一個 "default" 名稱

例如,上面的默認插槽,如果你想顯示調用的話,可以這樣:

<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 只能添加到 <template> 或自定義組件上,這點與棄用的 slot 屬性不同

作用域插槽

在 2.6.0+ 中已棄用

有時候,我們想在父組件中訪問子組件內部的一些可用數據。例如,假設有一個下面模板的 <current-user> 組件:

<span> <slot>{{ user.lastName }}</slot> </span> 復制代碼

我們可能想用用戶的名字來替換掉插槽里面的姓,於是我們這樣寫:

<current-user> {{ user.firstName }} </current-user> 復制代碼

很不幸,上面這段代碼不能如你預期那樣工作,因為當前代碼的作用域環境是在父組件中,所以它訪問不了 <current-user> 內部的數據。

為了解決這個, 我們可以在 <current-user> 內部的 <slot> 元素上動態綁定一個 user 對象屬性:

<span> <!-- 完整 v-bind:user 下面是簡寫形式 --> <slot :user="user"> {{ user.lastName }} </slot> </span> 復制代碼

綁定到 <slot> 元素上的屬性我們稱之為 slot props。現在,在父作用域中,我們可以通過 slot-scope 來訪問 user 數據了:

<current-user> <template slot-scope="slotProp"> {{ slotProp.user.firstName }} </template> </current-user> 復制代碼

同樣的,我們使用 v-slot 重構上面的代碼:

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

或者直接作用在 <current-user> 上的寫法:

<!-- 省略默認插槽名字 --> <current-user v-slot="slotProp"> {{ slotProp.user.firstName }} </current-user> <!-- 顯示調用默認插槽名字 --> <current-user v-slot:default="slotProp"> {{ slotProp.user.firstName }} </current-user> 復制代碼

在這個栗子中,我們選擇 slotProp 作為我們的 slot props 名字,但你可以使用你喜歡的任何名字。

單個默認插槽的縮寫形式

在上述情況下,當且僅當提供了默認插槽內容時,我們可以使用 v-slot 直接作用在組件上:

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

我們可以簡化上面的的默認插槽寫法:

<current-user v-slot="slotProps"> {{ slotProps.user.firstName }} </current-user> 復制代碼

請注意了,默認插槽的縮寫語法不能與具名插槽混用:

<!-- 控制台將報警告:--> <!-- To avoid scope ambiguity, the default slot should also use <template> syntax when there are other named slots. --> <!-- 意思就是說,為了避免作用域模糊 --> <!-- 當有其他具名插槽時,默認插槽也應當使用 '<template>' 模板語法 --> <current-user v-slot="slotProps"> {{ slotProps.user.firstName }} <template v-slot:other="otherSlotProps"> slotProps is NOT available here </template> </current-user> 復制代碼

於是,上面的代碼,我們改寫成:

<current-user> <!-- 兩種寫法均可 --> <!--<template v-slot="slotProps"> {{ slotProps.user.firstName }} </template>--> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> <template v-slot:other="otherSlotProps"> ... </template> </current-user> 復制代碼

插槽內容的解構賦值

在 Vue 代碼內部,我們傳遞的 slotProps 其實就是函數的一個單一參數:

function (slotProps) { // ... slot content ... } 復制代碼

這也就意味着 v-slot 的值只要滿足函數參數定義的 JavaScript 表達式的都可以接受。因此,在支持的環境(單文件或現代瀏覽器)中,你還可以使用 ES2015 解構語法來提取特定的插值內容,例如:

<current-user v-slot="{ user }"> {{ user.firstName }} </current-user> 復制代碼

代碼看起來更簡潔對吧。我們還可以重命名解構變量:

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

這給了我們很多自由操作的空間,你甚至可以自定義回退內容,以便在未定義插值情況下使用:

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

動態插槽名稱

2.6.0+ 新增

動態指令參數 也適用於 v-slot ,允許我們定義動態插槽名稱:

<base-layout> <template v-slot:[dynamicSlotName]> ... </template> </base-layout> 復制代碼

命名插槽簡寫

2.6.0+ 新增

v-onv-bind 類似,v-slot 也有一個簡寫,即使用 # 代替 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> 復制代碼

和其他指令一樣,只有在提供參數時才能使用簡寫形式,下面的寫法是無效的:

<!-- 將會觸發一個控制台警告 --> <current-user #="{ user }"> {{ user.firstName }} </current-user> 復制代碼

也就是說,如果你想使用簡寫語法,則務必指定插值的名字:

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


鏈接:https://juejin.im/post/5c64e11151882562e4726d98


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM