这节课我们继续来学习插槽,经过上节课的学习,我们初步了解了插槽的作用和简单的使用,这节课先来给大家补充一些插槽的基本概念。
<slot>
元素官方称之为插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在这里被渲染。
插槽默认内容
在使用插槽时,我们只声明了<slot>
但是没有给它提供插槽内容时,可以为插槽指定一个默认内容。在<slot>
标签之前设置默认内容。
const app = Vue.createApp({
data() {
return {
message: "hello world!"
}
},
template: `<div>
<Shop></Shop>
</div>`
})
app.component("Shop",{
template:`
<div>
<h2>欢迎来到购物商店</h2>
<slot>我是店员小黑</slot>
</div>
`
})
这样当我们没给组件传递插槽内容是,它会渲染slot中的默认内容“我是店员小黑”,
如果我们提供了别的内容,它渲染的就是我们指定的内容。
const app = Vue.createApp({
data() {
return {
message: "hello world!"
}
},
template: `<div>
<Shop>我是店员小朱</Shop>
</div>`
})
具名插槽
在一个组件中,我们可能会用到多个插槽来提高我们组件的灵活性,比如我们做了一个店铺组件,每个店铺都会有自己的店名,有自己的店员,有自己卖的商品,甚至还有不同装饰风格。在这样的一种需求下我们这个组件需要在不改变固定排版的情况,让它能够适应各式各样的店铺风格,提高灵活性。
好,那我们来看一下如何来使用多个插槽来实现上面的需求,目前我们只使用了一个插槽,显然是不够的。
我们需要为店名,店员,商品列表各提供一个插槽来实现自定义数据。
const app = Vue.createApp({
data() {
return {
message: "hello world!"
}
},
template: `<div>
<Shop>
<span>福乐家购物商店</span>
<span>我是店员小红</span>
<div>
<p>本店销售以下商品</p>
<ol>
<li>咖啡</li>
<li>可乐</li>
<li>泡面</li>
</ol>
</div>
</Shop>
</div>`
})
app.component("Shop",{
template:`
<div>
<h2>
<slot/>
</h2>
<div>
<slot />
</div>
<div>
<slot/>
</div>
</div>
`
})
按照我们的想法,我们设置了三个<slot/>
,但是我们会发现一个问题,我们不能给指定位置的插槽设置内容。无论怎么传递它得到的都是三个重复的内容,意思就是它把我们的插槽内容传递给了所有的<slot/>
。
这样不行啊,我们再对Shop组件改造一下,我们给slot元素设置一个name属性(第二个留着先不设置)
。其实设置nam属性的意思就是给插槽取名,让它有一个属于自己唯一的id。
给slot设置name属性以确保渲染指定的插槽内容——具名插槽
没有提供 name 时 <slot> 会隐式地命名为“default”
。
app.component("Shop",{
template:`
<div>
<h2>
<slot name="shopName"/>
</h2>
<div>
<slot />
</div>
<div>
<slot name="goodsList"/>
</div>
</div>
`
})
组件改成这样之后,我们来看一下如何来提供插槽内容给各个插槽出口。
const app = Vue.createApp({
data() {
return {
message: "hello world!"
}
},
template: `<div>
<Shop>
<template v-slot:shopName>福乐家购物商店</template>
<span>我是店员小红</span>
<template v-slot:goodsList>
<div>
<p>本店销售以下商品</p>
<ol>
<li>咖啡</li>
<li>可乐</li>
<li>泡面</li>
</ol>
</div>
</template>
</Shop>
</div>`
})
我们使用template
元素加 v-slot
指令 来给具名插槽传递内容
<template v-slot:shopName>福乐家购物商店</template>
v-slot指令可以简写为#,也就上面的代码可以改成:
<template #shopName>福乐家购物商店</template>
当我们没有使用含 v-slot
指令和 <template>
元素传递的数据,它就会默认传递给default 也就是没有定义name的<slot/>
。
好,这节课到此结束。