【vue】slot

默认slot
<body>
    <div id="root">
        <save-button></save-button>
    </div>
</body>
import Vue from "vue";

Vue.component("submit-button",{
    template:'<div>\
            <button>\
            <slot>Submit</slot>\
            </button>\
            </div>'
});
Vue.component("save-button",{
    template:'<submit-button>Save</submit-button>'
})
// Vue.component("save-button",{
//     template:'<submit-button></submit-button>'
// })
const vm = new Vue({
    el:"#root"
});

在这里插入图片描述

具名slot
  • H5新元素
    • header
    • nav
    • article
    • section
    • aside
    • footer
<body>
    <div id="root">
        <header>here is header</header>
        <nav>here is nav</nav>
        <div>
            <article>
                <section>here is article &gt; section</section>
            </article>
            <aside>here is aside</aside>
        </div>
        <footer>here is footer</footer>
    </div>
</body>

在这里插入图片描述

  • 具名slot
    • <template v-slot:对应的slot名称> </template>
    • <slot name="slot名称"></slot>
    • <template v-slot=""></template>的子内容将插入到<slot name=""><slot>所在位置
<body>
    <div id="root">
    <base-layout>
        <template v-slot:header>
            <h4>here is header</h4>
        </template>
        <template v-slot:default>
	        <p>here is the section</p>
	        <p>here is the content of the section</p>
        </template>
        <template v-slot:footer>
            <p>here is footer</p>
        </template>
    </base-layout>
    </div>
</body>
import Vue from "vue";

Vue.component("base-layout",{
    template:'<div class="container">\
        <header>\
            <slot name="header"></slot>\
        </header>\
        <section>\
            <slot name="default"></slot>\
        </section>\
        <footer>\
            <slot name="footer"></slot>\
        </footer>\
    </div>'
})

const vm = new Vue({
    el:"#root"
});

在这里插入图片描述

  • 具名slot的简写
    • v-slot:header简写成#header
    • v-slot:default简写成#default
    • v-slot:footer简写成#footer
<body>
    <div id="root">
    <base-layout>
        <template #header>
            <h4>here is header</h4>
        </template>
        <template #default>
            <p>here is the section</p>
            <p>here is the content of the section</p>
        </template>
        <template #footer>
            <p>here is footer</p>
        </template>
    </base-layout>
    </div>
</body>

在这里插入图片描述

<body>
    <div id="root">
    <base-layout>
        <template #header>
            <h4>here is header</h4>
        </template>
        <p>here is the section</p>
        <p>here is the content of the section</p>
        <template #footer>
            <p>here is footer</p>
        </template>
    </base-layout>
    </div>
</body>
import Vue from "vue";

Vue.component("base-layout",{
    template:'<div class="container">\
        <header>\
            <slot name="header"></slot>\
        </header>\
        <section>\
            <slot></slot>\
        </section>\
        <footer>\
            <slot name="footer"></slot>\
        </footer>\
    </div>'
})

const vm = new Vue({
    el:"#root"
});
作用域slot
<body>
    <div id="root">
    <current-user></current-user>
    </div>
</body>
import Vue from "vue";

Vue.component("current-user",{
    template:'<div>\
        <slot>{{user.lastname}}</slot>\
    </div>',
    data:function(){
        return {
            user:{
                firstname:"Steve",
                lastname:"Jobs",
                fullname:"Steve Jobs"
            }
        }
    }
})
const vm = new Vue({
    el:"#root"
});

在这里插入图片描述
但是,如果像下面这样

<body>
    <div id="root">
    <current-user>{{user.firstname}}</current-user>
    </div>
</body>

则会迎来“一丈红”。
在这里插入图片描述
这是因为user是组件current-user作用域下的变量,而父级访问不了组件current-user的作用域。
不过,作用域slot可以解决上面的问题。

  1. 组件current-user使用v-bind:user="user"将自身作用域下的user传递出来
  2. 父级使用v-slot:default="slotProps"通过slotProp.user接收过来
<body>
    <div id="root">
    <current-user v-slot:default="slotProps">
        {{slotProps.user.firstname}}
    </current-user>
    </div>
</body>
import Vue from "vue";

Vue.component("current-user",{
    template:'<div>\
        <slot v-bind:user="user">{{user.lastname}}</slot>\
    </div>',
    data:function(){
        return {
            user:{
                firstname:"Steve",
                lastname:"Jobs",
                fullname:"Steve Jobs"
            }
        }
    }
})
const vm = new Vue({
    el:"#root"
});

在这里插入图片描述
下面是作用域slot的几种写法。

  • 第一种,v-slot:default="slotProps"
<current-user v-slot:default="slotProps">
    {{slotProps.user.firstname}}
</current-user>
  • 第二种,简写形式,#default="slotProps"
<current-user #default="slotProps">
    {{slotProps.user.firstname}}
</current-user>
  • 第三种,如果只有默认slot,可省略default,即v-slot="slotProps"
<current-user v-slot="slotProps">
    {{slotProps.user.firstname}}
</current-user>
  • 第四种,使用解构赋值,v-slot="{user}"
<current-user v-slot="{user}">
    {{user.firstname}}
</current-user>
  • 第五种,使用别名v-slot="{user:person}"
<current-user v-slot="{user:person}">
    {{person.firstname}}
</current-user>
  • 第六种,设置默认值,v-slot='{user={firstname:"Nicholas"}}'
<current-user v-slot='{user={firstname:"Nicholas"}}'>
    {{user.firstname}}
</current-user>

在这里插入图片描述

作用域slot应用于组件复用
  • 不使用作用域slot
<body>
    <div id="root">
        <todo-list></todo-list>
    </div>
</body>
import Vue from "vue";

Vue.component("todo-list",{
    template:'<ul>\
        <li v-for="todo in list"\
            v-bind:key="todo.id">\
                {{todo.text}}\
        </li>\
    </ul>',
    data:function(){
        return {
            list:[
                {id:"#1",text:"吃饭"},
                {id:"#2",text:"睡觉"},
                {id:"#3",text:"打豆豆"}
            ]
        }
    }
})
const vm = new Vue({
    el:"#root"
});

在这里插入图片描述

  • 使用slot作用域
<body>
    <div id="root">
        <todo-list v-slot:default="{todo}">
            <span v-if="todo.isDone"></span>
            {{todo.text}}
        </todo-list>
    </div>
</body>
import Vue from "vue";

Vue.component("todo-list",{
    template:'<ul>\
        <li v-for="todo in list"\
            v-bind:key="todo.id">\
                <slot name="default" v-bind:todo="todo">\
                    {{todo.text}}\
                </slot>\
        </li>\
    </ul>',
    data:function(){
        return {
            list:[
                {id:"#1",text:"吃饭",isDone:true},
                {id:"#2",text:"睡觉",isDone:true},
                {id:"#3",text:"打豆豆",isDone:false}
            ]
        }
    }
})
const vm = new Vue({
    el:"#root"
});

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值