插槽在vue2.6.0開始有了新的更新
具名插槽(數據來自父組件)
子組件(定義插槽)這里版本前后沒什么變化
<template> <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> </template> <script> export default { name: "BaseLayout" } </script>
父組件(使用)這里版本后廢棄了slot="header"這樣的寫法,在vue3.0后直接移除。取而代之的是v-slot:插槽名稱的寫法,默認插槽(沒有名字,默認為default),縮寫為#header
<template> <base-layout> <template v-slot:header> <h1>Header</h1> </template> <template v-slot:default> <p>Main</p> </template> <template v-slot:footer> <p>Footer</p> </template> </base-layout> </template> <script> import BaseLayout from "../components/BaseLayout"; export default { components: {BaseLayout} } </script>
使用縮寫#的代碼
<template> <base-layout> <template #header> <h1>Header</h1> </template> <template #default> <p>Main</p> </template> <template #footer> <p>Footer</p> </template> </base-layout> </template> <script> import BaseLayout from "../components/BaseLayout"; export default { components: {BaseLayout} } </script>
頁面
作用域插槽(數據來自子組件)【2.6.0起,v-slot取代了slot和slot-scope】
子組件(定義了數據並且將數據綁定到特定屬性[user]上)
<template> <div> <header> <slot name="header"></slot> </header> <main> <!--綁定在 <slot> 元素上的特性被稱為插槽 prop--> <slot :user="userData"> {{userData.lastName}} </slot> </main> <footer> <slot name="footer"></slot> </footer> </div> </template> <script> export default { name: "BaseLayout", data: () => ({ userData: { firstName: 'AAA', lastName: 'Miss' } }) } </script>
父組件(給 v-slot
帶一個值來定義我們提供的插槽 prop 的名字[slotProps])這里廢棄了slot="default" slot-scope="slotProps"的寫法,直接v-slot:default="slotProps"或者#default="slotProps"
<template> <base-layout> <template #header> <h1>Header</h1> </template> <!--slotProps可以使任意名字--> <template #default="slotProps"> <strong style="color: crimson">{{slotProps.user.firstName}}</strong> </template> <template #footer> <p>Footer</p> </template> </base-layout> </template> <script> import BaseLayout from "../components/BaseLayout"; export default { components: {BaseLayout} } </script>
數據關系:
頁面:
以上代碼的意思是,本來這里的后備內容是顯示lastName的,我們可以在父組件那里做手腳,讓后備內容顯示的是firstName。但是無論怎么做,數據都是來自子組件。
將父組件的指定的后備內容注釋掉即可顯示原生的內容,如下:
頁面:
另外一個例子(寫一個表格組件,靈感來源於Vuetify框架,沒讀過它的內部實現,但是一眼能看出使用了插槽,根據我的理解寫出下面的例子)
定義:MyTable.vue
<template> <table> <slot name="headers"> <tr> <th v-for="h in headers" :key="h">{{h}}</th> </tr> </slot> <!--這里的插槽prop綁定了當前的數據 :items="i" --> <slot name="items" v-for="i in items" :items="i"> <tr :key="i[itemKey]" :title="i[itemKey]"> <td v-for="j in i" :key="j">{{j}}</td> </tr> </slot> </table> </template> <script> export default { name: "MyTable", // 自定義屬性 props: ["headers","items","itemKey"], } </script> <style scoped> table{ width: 200px; margin: 25px auto; border-collapse: collapse; border: 1px solid #ddd; } table tr,table td{ border-collapse: collapse; border: 1px solid #ddd; padding: 8px 10px; } </style>
使用:
<template> <div class="about"> <!-- ********************作用域插槽的應用******************** --> <!--直接使用--> <my-table :headers="headersData" :items="itemsData" item-key="id"></my-table> <!--父組件利用插槽自定義--> <my-table :headers="headersData" :items="itemsData" item-key="id"> <!--有了作用域插槽,可以由父組件來改變子組件的展示效果--> <!--在父級作用域中,我們可以給 v-slot 帶一個【值】來定義我們提供的插槽 prop 的名字--> <!--【值】也就是那個 props,可以為任意名字--> <template v-slot:items="props"> <tr> <td style="color: darkcyan">{{props.items.id}}</td> <td style="color: darkcyan">{{props.items.name}}</td> <td style="color: darkcyan">{{props.items.age}}</td> </tr> </template> </my-table> <!-- ********************作用域插槽的應用******************** --> </div> </template> <script> import MyTable from "../components/MyTable"; export default { name: 'about', components: {MyTable}, data: () => ({ headersData: ["ID", "Name", "Age"], itemsData: [ {id: 1, name: 'A', age: 10}, {id: 2, name: 'B', age: 20}, {id: 3, name: 'C', age: 12}, {id: 4, name: 'D', age: 15} ] }) } </script> <style scoped> </style>
頁面:(前者直接使用,后者利用作用於插槽改變了顏色)
變量關系
其它
對於默認插槽,我們可以變成更加簡潔的寫法:
<template v-slot:default="slotProps"> <strong style="color: crimson">{{slotProps.user.firstName}}</strong> </template>
變成(不帶參數的 v-slot
被假定對應默認插槽)
<template v-slot="slotProps"> <strong style="color: crimson">{{slotProps.user.firstName}}</strong> </template>
對於縮寫 #,有限制條件,那就是只能有參數名的情況下才能使用,即:#header=“”。而不帶的話會報錯,即:#=“”