• Vue(六)插槽(2.6.0+)


    插槽在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=“”。而不带的话会报错,即:#=“”

  • 相关阅读:
    Protocol Buffers教程
    Paxos、ZAB、RAFT协议
    kafka自定义序列化器
    Java cas原理
    常见的排序算法
    Java反射
    etcd单机集群
    通过tomcat shutdown port关闭tomcat
    Java ConcurrentHashMap初始化
    LaTeX技巧892: Ubuntu 安装新版本TeXLive并更新
  • 原文地址:https://www.cnblogs.com/LUA123/p/10812164.html
Copyright © 2020-2023  润新知