slot(插槽)的概念是把外层的内容塞进子元件的指定位置里。跟插槽的字面意思一样,前提是:有插口才能插。子元件需要开一个插口(slot),才可以在外层元件把内容塞进子元件里。
slot(插槽) 可分为四种:
以下会再作详细解说。
先讲解第一个最简单使用 slot 的方法。
假设有一个叫 Card
的元件,我们想要从父层,把「夏日短裙」这文字塞进这个元件(即是子层),就可使用slot
:
结果:
以上就是 slot 概念:在外层把内容塞到子元件的指定位置里。这就是预设插槽,也是最简单的用法。
避免没有传入内容,可以设定显示预值内容:
App.vue
<template>
<Card></Card>
</template>
Card.vue
<template>
<h1>
<slot>这是预设文字</slot>
</h1>
</template>
以上结果就会渲染「这是预设文字」。
借用这篇文章的解说例子,用下图就能理解为什麽要使用具名插槽:
图片来源:https://dev.to/samanthaming/how-i-m-using-vue-slots-on-my-site-nfn
假设有一个有很多工具的工具箱(父层内容),现在要把它们放到一个盒子里的不同间隔范围里(子元件)。这时候,盒子里要标示清楚这个范围是放什麽工具。正如在子元件里,要使用具名插槽来指定父层的内容要被指派塞进什麽地方。
例子:
结果:
注意:如果 slot 没有命名,在父元件传入内容时,需使用 v-slot:default
来标示。
另外,缩写可以用 #
代替 v-slot:
:
<Card>
<template #title>
<h1> 夏日短裙 </h1>
</template>
<template #price>
<p> $200 </p>
</template>
<template #default>
<p> Sizes: XS, S, M, L </p>
</template>
</Card>
在进入介绍最後一个 slot 用法,scoped slot 之前。先理解为什麽需要用 slot。props 与 slot 的分别是:
<p> $200 </p>
这个 DOM 内容转入子元件里,这情况用 slot 就会方便很多。参考 Mike 老师这个影片,他有提到使用 slot 打造自己的 UI 元件。过程就如自行制作一个 Vue 模版,利用 named slot 预先在分配资料的位置。当父层传入资料时,就自动把父层的资料,分配到子元件的不同位置里。
举例说,如果一个网页的每个 section heading 都有同一个样式,我可以把 heading 拆成一支独立档案。再同时利用 named slot 分配好不同资料的位置。这样的好处是:
Heading.vue
<template>
<div class="section">
<h2>
<slot name="title"></slot>
</h2>
<p>
<slot name="slogan"></slot>
</p>
</div>
</template>
App.vue
<Heading v-for="section in sections" :key="section.title">
<template #title>
{{ section.title }}
</template>
<template #slogan>
{{ section.slogan }}
</template>
</Heading>
export default {
components: {
Heading,
},
data() {
return {
sections: [
{
title: "限时优惠",
slogan: "抢购限时最便宜货品!",
},
{
title: "最新商品",
slogan: "为你带来最新货品!",
},
{
title: "一般商品",
slogan: "多种商品任你选择!",
},
],
};
},
};
结果:
Scoped slot 是指把子元件的资料取出来,给父层使用。这是因为父层无法取得子元件的资料。
举例说,每个商品都用一个 Card 元件来呈现。商品资料在父层,而 Card 的资料呈现和样式就在 Card 元件里面。像以下结构:
App.vue
<Card>
<template #title>...</template>
<template #price>...</template>
<template #size>...</template>
</Card>
export default {
components: {
Card,
},
data() {
return {
items: [
{
title: "夏日短裙",
price: 200,
sizes: ["XS", "S", "M", "L"],
},
{
title: "纯白 T-shirt",
price: 100,
sizes: ["XS", "S"],
},
{
title: "针织背心",
price: 300,
sizes: ["XS", "S", "M"],
},
],
};
},
};
components/Card.vue
<div class="card">
<h1 class="title">
<slot name="title"></slot>
</h1>
<p>
售价:
<slot name="price"></slot>
</p>
<p>
<slot name="size"></slot>
</p>
<div class="quantity">
<label for="quantity">数量:</label>
<select name="quantity" id="quantity" v-model="quantity">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<p class="result">
<slot name="result" :quantity="quantity" ></slot>
</p>
</div>
export default {
data() {
return {
quantity: 0
}
}
};
结果每个 Card 都会长这样:
在这情况中,数量的 select 在子元件(Card.vue)里。可是,父层需要利用子元件 select 的结果,组成:已选购:{{ item.title }} x {{ quantity}}
这字串,再塞回子元件的 <slot name="result"></slot>
里面。
解决方法:
在子元件(Card.vue) 的 slot 里绑定 prop(我们称为 slot props),然後在父层的相应 template
里取出来用,并且组字串,塞回子元件里。
父层 App.vue
<template #result="slotProps">
已选购:{{ item.title }} x{{ slotProps.quantity }}
</template>
子元件 Card.vue
<p class="result">
<slot name="result" :quantity="quantity"></slot>
</p>
注意,props 名称不一定叫 slotProps,可自定义其他名称。再简洁一点,使用解构写法:
<template #result="{ quantity }">
已选购:{{ item.title }} x{{ quantity }}
</template>
https://codesandbox.io/s/scoped-slot-yong-fa-dxqh4?file=/src/App.vue:320-416
Vuetify是一个提供给Vue开发者的material UI 框架。
它有大量使用Scoped slot,让开发者客制化Vuetify里封装好的元件,以 table 这元件为例。这里有使用scoped slot,指定要更改Calories这个item里的内容:
动态插槽很简单,就是在父层可以动态指定不同 slot,把内容塞到子元件里。
父层,使用中括号动态指定 slot:
<template>
<div v-for="area in areas" :key="area">
<input type="radio" :id="area" :value="area" v-model="chosenArea">
<label :for="area"> {{ area }} </label>
</div>
<Color>
<template v-slot:[chosenArea]>
<span>我现在在: {{ chosenArea }}</span>
</template>
</Color>
</template>
data() {
return {
chosenArea: 'nav',
areas: ['nav', 'main', 'footer']
}
}
子层,动态建立slot:
<p v-for="area in areas" :key="area" :class="area">
<slot :name="area"></slot>
</p>
export default {
data() {
return {
areas: ['nav', 'main', 'footer']
}
}
}
<style>
.nav {
color: red;
}
.main {
color: black;
}
.footer {
color: blue;
}
</style>
https://codesandbox.io/s/dynamic-slot-shi-fan-4yenc
Vue.js: slots vs. props
How I'm using Vue Slots on my site
The Difference Between Props, Slots and Scoped Slots in Vue.js
重新认识 Vue.js - 2-4 编译作用域与 Slot 插槽
Vue slots 使用超入门
复用元件的好帮手:Vue Slots(v-slot、Scoped Slots)
<<: #11-下滑动态做起来!(JS: scrollTo & scrollBy)
>>: [Android Studio 30天自我挑战] Progress Bar练习
前言 昨天我们设计好UI介面後, 我们有一堆按钮和文字框的"元件", 要让这些元...
前言 JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用...
程序基本结构 程序的基本结构可概分为循序式结构、选择式结构,与重复式结构三种,几乎是在循序结构式的基...
看这个程序码,结果会是如何? function ArrFunction(){ var arr=[];...
Migration 是资料库的版本控制,让你和你的团队能够互相去共想资料库的结构,你是否曾经曾告诉你...