默认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 > 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可以解决上面的问题。
- 组件
current-user
使用v-bind:user="user"
将自身作用域下的user
传递出来 - 父级使用
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"
});