开篇寄语
在上一篇介绍了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; }
生成效果如下所示:
- 我的微信
- 微信扫一扫加好友
- 我的微信公众号
- 扫描关注公众号