Vue 2.6
已經發布一段時間了,主要的更新就是slot
(插槽)。可能不少人從始至終都沒用過slot
,那多是你對它不夠了解,當你真正的瞭解它的時候,你就會知道當你封裝一個可複用插件的時候它是多麼的 perfect~html
代碼已放到Github上。能夠下載跟着練習一下。vue
咱們先看一個簡單的例子:git
<!--子組件-->
<template>
<button class="custom-button">
<slot></slot>
</button>
</template>
<style>
.custom-button{
color: #fff;
background-color: #409eff;
padding: 10px 20px;
font-size: 14px;
border-radius:6px;
outline: none;
border: 1px solid #dcdfe6;
}
</style>
複製代碼
<!--父組件-->
<template>
<div class="button-list">
<cus-bottom>肯定</cus-bottom>
</div>
</template>
<script>
import customButton from './customButton.vue'
export default{
components:{
'cus-bottom':customButton
}
}
</script>
複製代碼
最終渲染:github
<div class="button-list">
<button class="custom-button">
肯定
</button>
</div>
複製代碼
當子組件渲染的時候,<slot></slot>
將會被替換爲「肯定」。slot
是不會被渲染的,它是用來接收父組件傳過來的內容。bash
咱們來看一張圖,我以爲更容易理解插槽的概念:ide
遊戲卡就是父組件傳給的內容,插口就至關於子組件的slot
標籤,組合起來就是最終的渲染。
固然上述就是最簡單的slot
的使用,咱們接着往下看。ui
<slot></slot>
不只能夠接受字符串,還能夠接收Html模板:spa
<!--父組件-->
<div class="button-list">
<cus-bottom>
<span>肯定</span>
</cus-bottom>
</div>
複製代碼
最終渲染:插件
<div class="button-list">
<button class="custom-button">
<span>肯定</span>
</button>
</div>
複製代碼
還能夠接收其餘組件:code
<!--父組件-->
<div class="button-list">
<cus-bottom>
<!-- cus-font 圖標組件 -->
<cus-font></cus-font>
<span>肯定</span>
</cus-bottom>
</div>
複製代碼
咱們用例子來解釋一下什麼叫 編譯做用域
<!--父組件-->
<template>
<div class="button-list">
<cus-bottom>{{buttonText}}</cus-bottom>
</div>
</template>
<script>
import customButton from './customButton.vue'
export default{
components:{
'cus-bottom':customButton
},
data(){
return{
buttonText:'保存'
}
}
}
</script>
複製代碼
{{buttonText}}
是父組件中的編譯的,因此子組件獲取不到buttonText
變量,反之在子組件內編譯的變量父組件也獲取不到。
官網叫後備內容。我以爲有點怪,這裏就叫默認內容。
當咱們button
默認內容就是「肯定」:
<button class="custom-button">
<!--這裏的肯定就是默認內容-->
<slot>肯定</slot>
</button>
複製代碼
如今當我在一個父級組件中使用<cus-button>
而且按鈕也是「肯定」的時候,就能夠不提供任何內容:
<div class="button-list">
<cus-bottom></cus-bottom>
</div>
複製代碼
固然若是咱們父組件裏的按鈕是「保存」的時候,還能夠這樣寫
<div class="button-list">
<!--這裏的保存 會替換掉子組件的默認內容-->
<cus-bottom>保存</cus-bottom>
</div>
複製代碼
最終渲染:
<div class="button-list">
<button class="custom-button">
保存
</button>
</div>
複製代碼
具備名字的插槽。爲何要有這個東西呢?咱們在上面的例子中
slot
只有一個,因此父組件傳過來的內容都被子組件惟一的slot
接收了。可是不少時候咱們須要有多個slot
來分別接收父組件傳過來的 '多份' 內容。
這裏咱們使用官網的例子,帶有以下內容的 <base-layout>
組件:
<div class="container">
<header>
<!-- 咱們但願把頭部內容放在這裏 -->
</header>
<main>
<!-- 咱們但願把主要內容放在這裏 -->
</main>
<footer>
<!-- 咱們但願把頁腳放在這裏 -->
</footer>
</div>
複製代碼
如今我須要三個slot
(插槽),來接收父組件傳過來的三分內容。對於這樣的狀況,slot
元素有一個特殊的特性:name。這個特性能夠用來定義額外切獨立的插槽:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
複製代碼
中間一個不帶 name 的 slot
的插槽 會帶有隱含的名字「default」。至關於<slot name="default"></slot>
。也就是說如今子組件裏有三個名爲:header
default
footer
的插槽。
那麼如今父組件使用 <base-layout>
組件的時候須要傳三分內容(都不是必須的),'header','default','footer'。這個時候就須要有個標識告訴子組件三分內容跟三個插槽如何對應上。
在向具名插槽提供內容的時候,咱們能夠在一個 <template>
元素上使用 v-slot
指令,並以 v-slot
的參數的形式提供其名稱:
<base-layout>
<template v-slot:header>
<h1>這是header插槽的內容</h1>
</template>
<p>這裏是default插槽的內容</p>
<p>這裏也是default插槽的內容</p>
<template v-slot:footer>
<p>這是footer插槽的內容</p>
</template>
</base-layout>
複製代碼
v-slot
:後面就是子組件對應的slot
的name
。由於子組件main標籤裏的slot
沒有name
,默認name = default
,因此還能夠這樣寫
<base-layout>
<template v-slot:header>
<h1>這是header插槽的內容</h1>
</template>
<template v-slot:default>
<p>這裏是default插槽的內容</p>
<p>這裏也是default插槽的內容</p>
</template>
<template v-slot:footer>
<p>這是footer插槽的內容</p>
</template>
</base-layout>
複製代碼
最終渲染:
<div class="container">
<header>
<h1>這是header插槽的內容</h1>
</header>
<main>
<p>這裏是default插槽的內容</p>
<p>這裏也是default插槽的內容</p>
</main>
<footer>
<p>這是footer插槽的內容</p>
</footer>
</div>
複製代碼
跟 v-on
和 v-bind
同樣,v-slot
也有縮寫,即把參數以前的全部內容 (v-slot:
) 替換爲字符 #
。例如 v-slot:header
能夠被重寫爲 #header
:
<base-layout>
<template #header>
<h1>這是header插槽的內容</h1>
</template>
<template #default>
<p>這裏是default插槽的內容</p>
<p>這裏也是default插槽的內容</p>
</template>
<template #footer>
<p>這是footer插槽的內容</p>
</template>
</base-layout>
複製代碼
這裏講做用域插槽我以爲叫插槽傳值更貼切。
例如,設想一個帶有以下模板的 <current-user>
組件:
<template>
<span>
<slot>{{ userInfo.name }}</slot>
</span>
</template>
<script>
export default{
data(){
return{
userInfo:{
name:'erdong',
sex:'boy',
age:'26'
}
}
}
}
</script>
複製代碼
包括當前用戶的全部信息。插槽的默認內容是name。當咱們使用 <current-user>
組件時:
父組件:
<current-user></current-user>
複製代碼
最終渲染:
<span>
erdong
</span>
複製代碼
可是我想讓父組件裏顯示sex
該怎麼辦呢?很簡單,改變子組件的插槽的默認內容:
<span>
<slot>{{ userInfo.sex }}</slot>
</span>
複製代碼
可是這樣達不到咱們封裝組件的特性:可複用性。
若是說父組件能拿到子組件裏的infoData
的值,那咱們就能夠這樣寫:
<!--父組件-->
<current-user>
{{infoData.sex}}
</current-user>
複製代碼
這樣就能覆蓋子組件裏的默認內容。可是咱們在上面提到了 編譯做用域 父組件是取不到子組件的變量的。
想讓父組件取到infoData
該怎麼辦呢?
這個時候咱們須要更改子組件:
<!--子組件-->
<span>
<slot v-bind:userInfo="userInfo" name='user'>{{ userInfo.sex }}</slot>
</span>
複製代碼
父組件:
<current-user>
<template v-slot:user="infoData">
{{infoData.userInfo.sex}}
</template>
</current-user>
複製代碼
最終渲染:
<span>
boy
</span>
複製代碼
子組件v-bind:userInfo="userInfo" name='user'
第一個userInfo
是傳給父組件的變量名稱,第二個userInfo
是傳給父組件的值。name
就是該slot
的名稱
父組件v-slot:user="infoData"
user
就是對應子組件的slot
的name
,infoData
就是接收該slot
傳過來的值的集合的變量名稱。爲何叫集合呢?由於子組件一個slot能夠傳多個值:
<!--子組件-->
<template>
<span>
<slot v-bind:userInfo="userInfo" v-bind:address='address' name='user'>{{ userInfo.name }}</slot>
</span>
</template>
<script>
export default{
data(){
return{
userInfo:{
name:'erdong',
sex:'boy',
age:'26'
},
address:{
city:'上海市',
}
}
}
}
</script>
複製代碼
<!--父組件-->
<current-user>
<template v-slot:user="infoData">
{{infoData.userInfo.sex}}{{infoData.address.city}}
</template>
</current-user>
複製代碼
最終渲染:
<span>
boy上海市
</span>
複製代碼
<!--父組件-->
<current-user>
<template v-slot:user="infoData">
{{infoData.userInfo.sex}}{{infoData.address.city}}
</template>
</current-user>
複製代碼
上面提到了 infoData
是子組件名爲user
的插槽傳過來的值得集合。 即:
infoData = {
userInfo:{
name:'erdong',
sex:'boy',
age:'26'
},
address:{
city:'上海市',
}
}
複製代碼
因此咱們能夠用ES6的語法來解構它:
<!--父組件-->
<current-user>
<template v-slot:user="{userInfo,address}">
{{userInfo.sex}}{{address.city}}
</template>
</current-user>
複製代碼
到這裏咱們基本上就把Vue
的slot
(插槽)使用過了一遍,還有一些沒有提到,可是若是這些你所有學會的話,能夠說你已經掌握了slot
的使用。若是報錯請查看你的Vue.js版本是不是2.6.x。
在上面咱們用封裝button的例子來說slot的基本用法。有興趣的同窗能夠完善一下。封裝一個相似於element UI
的button
組件。能夠留着本身項目使用。