Vue(六)插槽(2.6.0+)

插槽在vue2.6.0開始有了新的更新vue

具名插槽(數據來自父組件)

子組件(定義插槽)這裏版本先後沒什麼變化框架

<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>

使用縮寫#的代碼spa

<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>

 

頁面code

 

做用域插槽(數據來自子組件)【2.6.0起,v-slot取代了slot和slot-scope】

子組件(定義了數據而且將數據綁定到特定屬性[user]上component

<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"blog

<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>

數據關係:ip

頁面:作用域

以上代碼的意思是,原本這裏的後備內容是顯示lastName的,咱們能夠在父組件那裏作手腳,讓後備內容顯示的是firstName。可是不管怎麼作,數據都是來自子組件。string

將父組件的指定的後備內容註釋掉便可顯示原生的內容,以下:

 

頁面:

另一個例子(寫一個表格組件,靈感來源於Vuetify框架,沒讀過它的內部實現,可是一眼能看出使用了插槽,根據個人理解寫出下面的例子)

定義:MYTable.vue

<template>
    <!--這裏的自定義屬性負責顯示父組件傳遞的數據,僅供測試,能夠忽略不寫-->
    <table :items="items" :headers="headers" :item-key="itemKey">
        <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>
    <base-layout>
        <template #header>
            <h1>Header</h1>
        </template>
        <!--slotProps能夠使任意名字-->
        <template v-slot="slotProps">
            <strong style="color: crimson">{{slotProps.user.firstName}}</strong>
            <!-- ********************做用域插槽的應用******************** -->
            <!--直接使用-->
            <m-y-table
                    :headers="headersData"
                    :items="itemsData"
                    item-key="id"
            ></m-y-table>
            <!--父組件利用插槽自定義-->
            <m-y-table
                    :headers="headersData"
                    :items="itemsData"
                    item-key="id"
            >
                <!--有了做用域插槽,能夠由父組件來改變子組件的展現效果-->
                <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>
            </m-y-table>
            <!-- ********************做用域插槽的應用******************** -->
        </template>

        <template #footer>
            <p>Footer</p>
        </template>
    </base-layout>
</template>
<script>
    import BaseLayout from "../components/BaseLayout";
    import MYTable from "../components/MYTable";
    export default {
        components: {MYTable, BaseLayout},
        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>

 

頁面:(前者直接使用,後者利用做用於插槽改變了顏色

變量關係

其它

對於默認插槽,咱們能夠變成更加簡潔的寫法:

<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=「」。而不帶的話會報錯,即:#=「」

相關文章
相關標籤/搜索