
开篇寄语
在上一篇介绍了Vuejs的组件开发,具体可以参看下方的前情提要,而本篇文章继续沿着上一篇的内容说开去,即向深层次去理解Vuejs中组件的开发。
前情提要
内容详情
以下内容是以Vue3版本来说的,虽然与Vue2版本区别不是很大。
上一篇文章讲了如何用vuejs开发组件的基本知识,那么问题来了,在组件内部定制化内容,同样一个模板<template></template>但是显示的样子不一样,也就是说引用模板时要处理构造的组件数据,就需要引入一个名为‘slots’的概念了。
Vuejs的文档是这样写的:
Vue implements a content distribution API inspired by the Web Components spec draft (opens new window), using the element to serve as distribution outlets for content.
组件是现代 Web 应用程序开发的核心。每个应用程序都由许多组件组成,这些组件平滑地拼接在一起,以便作为一个整体运行。这些组件需要最大程度地灵活和可重用,以允许在不同的情况下甚至在不同的应用程序中使用它们。许多框架用来满足这些要求的主要机制之一——尤其是 Vue——被称为“slot”。
Slot是一种功能强大且通用的内容分发和组合机制。您可以将Slot视为可定制的模板(例如,类似于 PHP 模板),您可以在不同的地方使用它们,针对不同的用例,产生不同的效果。例如,在像 Vuetify 这样的 UI 框架中,常用于制作通用组件,例如警报组件。在这些类型的组件中, Slot用作默认内容和任何附加/可选内容(例如图标、图像等)的占位符。
Slot允许您向特定组件添加任何结构、样式和功能。通过使用Slot,开发人员可以大大减少单个组件中使用的 props 数量,使组件更加干净和易于管理。
试举一例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Demo</title>
</head>
<body>
<div id="app">
<com-input></com-input>
<com-input>
<template v-slot="slot">
<span>{{ slot.data.join(' * ') }}</span>
</template>
</com-input>
<com-input>
<template v-slot="slot">
<span>{{ slot.data.join(' - ') }}</span>
</template>
</com-input>
</div>
<template id="cpn">
<div>
<slot :data="Language">
<ul>
<li v-for="(item, index) in Language" :key="index">{{ item }}</li>
</ul>
</slot>
</div>
</template>
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
isShow: true
}
},
});
app.component('com-input', {
template: "#cpn",
data() {
return {
isShwo: false,
Language: ['Japanese', 'English', 'Chinese', 'Korean']
}
},
})
app.mount("#app")
</script>
</body>
</html>
生成效果如下所示:

可以通过以上例子看出,在处理模板数据中,以slot位标志的内容,如下所示:
<div id="app">
<com-input></com-input>
<com-input>
<template v-slot="slot">
<span>{{ slot.data.join(' * ') }}</span>
</template>
</com-input>
<com-input>
<template v-slot="slot">
<span>{{ slot.data.join(' - ') }}</span>
</template>
</com-input>
</div>
<template id="cpn">
<div>
<slot :data="Language">
<ul>
<li v-for="(item, index) in Language" :key="index">{{ item }}</li>
</ul>
</slot>
</div>
</template>
其中比较关键的就是v-slot的使用。
通过上面通俗易通的例子,是不是对slot有了一定的理解了?
为了照顾大多数初次接触Vue.js的朋友,接下来讲一下如何从头开始构建slot的过程以加深理解。
基本上,Vue 提供两种slot:简单slot和作用域slot。让我们从简单的开始。考虑以下示例:
const app = Vue.createApp({})
app.component('primary-button', {
template: `
<button>
<slot>OK</slot>
</button>`
})
app.mount('#app')
在这里,我们有一个主要的按钮组件。我们希望按钮的文本是可自定义的,因此我们使用按钮元素内的slot组件为文本添加占位符。我们还需要一个默认(后备)通用值,以防我们不提供自定义值。 Vue 使用我们放在 slot 组件中的所有内容作为默认 slot 内容。所以我们只是将文本“OK”放在组件中。现在我们可以像这样使用组件:
<div id="app"> <primary-button></primary-button> </div>
结果是一个带有文本“OK”的按钮,因为我们没有提供任何值。但是如果我们想创建一个带有自定义文本的按钮怎么办?在这种情况下,我们在组件实现中提供自定义文本,如下所示:
<div id="app"> <primary-button>Subscribe</primary-button> </div>
在这里,Vue 采用自定义的“Subscribe”文本并替代了之前的”OK“。
以上的示例很简单吧,那接下来咱们来点难的。
const app = Vue.createApp({})
app.component('quote', {
template: `
<article>
<h2>The quote of the day says:</h2>
<p class="quote-text">
<slot></slot>
</p>
</article>`
})
app.mount('#app')
<div id="app">
<quote>
<div class="quote-box">
"Creativity is just connecting things."
<br><br>
- Steve Jobs
</div>
</quote>
</div>
.quote-box {
background-color: lightgreen;
width: 300px;
padding: 5px 10px;
}
.quote-text {
font-style: italic;
}
在这个例子中,我们创建了一个内容不变的标题标题,然后我们在一个段落中放置了一个slot组件,其内容将根据当天的引用而变化。当组件被渲染时,Vue 将显示来自引用组件的标题,然后是我们放在引用标签中的内容。还要注意引用创建和实现中使用的 CSS 类。我们可以根据需要以两种方式设置组件的样式。
继续让它动态化,引入一个Api,自动生成随机的经典名言,如下所示:
const app = Vue.createApp({
data() {
return {
quoteOfTheDay: null,
show: false
};
},
methods: {
showQuote() {
axios.get('https://favqs.com/api/qotd').then(result => {
this.quoteOfTheDay = result.data
this.show = true
});
}
}
})
app.component('quote', {
template: `
<article>
<h2>The quote of the day says:</h2>
<p class="quote-text">
<slot></slot>
</p>
</article>`
})
app.mount('#app')
<div id="app">
<quote>
<button v-if="show == false" @click="showQuote">Show Quote of the Day</button>
<div v-if="show" class="quote-box">
{{ quoteOfTheDay.quote.body }}
<br><br>
- {{ quoteOfTheDay.quote.author }}
</div>
</quote>
</div>
.quote-box {
background-color: lightgreen;
width: 300px;
padding: 5px 10px;
}
.quote-text {
font-style: italic;
}
生成效果如下所示:
- 我的微信
- 微信扫一扫加好友
-
- 我的微信公众号
- 扫描关注公众号
-






