Vue老虎机的综合指南

154 阅读5分钟

组件是现代网络应用程序开发的核心。每个应用程序都是由一些组件顺利地拼接在一起,以便作为一个整体工作。这些组件需要有最大的灵活性和可重用性,以便在不同的情况下,甚至在不同的应用程序中使用它们。许多框架用来满足这种要求的主要机制之一--在Vue中--被称为 "槽"。

槽是一种强大而通用的内容分发和组合机制。你可以把槽看作是可定制的模板(例如类似于PHP模板),你可以在不同的地方使用,用于不同的用例,产生不同的效果。例如,在像Vuetify这样的UI框架中,槽被用来制作通用组件,如警报组件。在这些类型的组件中,槽被用作默认内容和任何额外/可选的内容的占位符,如图标、图像等。

槽允许你为一个特定的组件添加任何结构、风格和功能。通过使用槽,开发者可以大大减少单个组件中使用的道具的数量,使组件更加简洁和易于管理。

在本教程中,我们将探讨如何在Vue 3的背景下利用槽的力量。让我们开始吧。

插槽的基本用法

基本上,Vue提供了两种槽:一种是简单的槽,另一种是范围槽。让我们从简单的槽开始。考虑一下下面的例子。

const app = Vue.createApp({})

app.component('primary-button', {
  template: `
    <button>
      <slot>OK</slot>
    </button>`
})

app.mount('#app')

这里,我们有一个主要的按钮组件。我们希望按钮的文本是可定制的,所以我们在button 元素内使用slot 组件,为文本添加一个占位符。我们还希望有一个默认(回退)的通用值,以防我们没有提供一个自定义的。Vue将我们放在slot 组件内的所有内容作为默认的插槽内容。所以我们只是把文本 "OK "放在组件里。现在我们可以像这样使用该组件。

<div id="app">
  <primary-button></primary-button>
</div>

请看笔
Vue 3槽。Basic Slot by SitePoint (@SitePoint)
onCodePen.

结果是一个文本为 "OK "的按钮,因为我们还没有提供任何值。但如果我们想创建一个带有自定义文本的按钮呢?在这种情况下,我们可以像这样在组件实现中提供自定义文本。

<div id="app">
  <primary-button>Subscribe</primary-button>
</div>

在这里,Vue接受了自定义的 "订阅 "文本,并使用它代替了默认文本。

正如你所看到的,即使在这个简单的例子中,我们在如何呈现我们的组件方面得到了很大的灵活性。但这仅仅是冰山一角。让我们来看看一个更复杂的例子。

构建 "每日报价 "组件

现在,我们将建立一个显示当天报价的报价组件。下面是代码。

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;
}

在这个例子中,我们创建了一个标题,其内容将是恒定的,然后我们把一个槽组件放在一个段落内,其内容将根据当天的报价而变化。当该组件被渲染时,Vue将显示来自报价组件的标题,然后是我们放在报价标签内的内容。还要注意在报价创建和实现中都使用了CSS类。我们可以根据自己的需要,用两种方式来设计我们的组件。

参见笔者
Vue 3槽。Quote Component by SitePoint (@SitePoint)
onCodePen.

我们的每日报价组件运行良好,但我们仍然需要手动更新报价。让我们通过使用Fav Quotes 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.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>

在这里,我们使用Axios调用 "每日报价 "API端点,然后我们使用返回的JSON对象中的bodyauthor 属性来填充报价。因此,我们不再需要手动添加报价;它是自动完成的。

见笔
Vue 3槽。CodePen上的SitePoint (@SitePoint) 的Axios报价组件

使用多个槽

尽管单个槽的功能相当强大,但在很多情况下这是不够的。在现实世界的场景中,我们往往需要不止一个槽来完成工作。幸运的是,Vue允许我们根据需要使用多个槽。让我们看看如何通过构建一个简单的卡片组件来使用多个槽。

构建一个基本的卡片组件

我们将建立一个有三个部分的卡片组件:标题、主体和页脚。

const app = Vue.createApp({})

app.component('card', {
  template: `
    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>`
})

app.mount('#app')
<div id="app">
  <card>
    <template v-slot:header>
      <h2>Card Header Title</h2>
    </template>

    <template v-slot:default>
      <p>
        Lorem ipsum leo risus, porta ac consectetur ac, vestibulum at eros. Donec id elit non mi porta gravida at eget metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras mattis consectetur purus sit amet fermentum.
      </p>
    </template>

    <template v-slot:footer>
      <a href="#">Save</a> -
      <a href="#">Edit</a> -
      <a href="#">Delete</a>
    </template>
  </card>
</div>

为了使用多个槽,我们必须为每个槽提供一个名称。唯一的例外是默认槽。因此,在上面的例子中,我们为页眉和页脚槽添加了一个name 属性。没有提供名称的槽被认为是默认的。

当我们使用card 组件时,我们需要使用template 元素与v-slot 指令,槽名为:v-slot:[slot-name]

参见笔者
Vue 3槽。Card Component by SitePoint (@SitePoint)
onCodePen.

注意:v-slot 指令有一个快捷方式,它使用特殊的符号# ,后面是插槽的名称。因此,例如,我们可以不写v-slot:header ,而写#header

命名的槽也可以与第三方组件一起使用,我们将在下一节看到。

在Bulma的卡片组件中使用命名的插槽

让我们对Bulma's Card组件做一些调整。

const app = Vue.createApp({})

app.component('card', {
  template: `
    <div class="container">
      <div class="card">
        <header class="card-header">
          <slot name="header"></slot>
        </header>
        <main class="card-content">
          <slot></slot>
        </main>
        <footer class="card-footer">
          <slot name="footer"></slot>
        </footer>
      </div>
    </div>`
})

app.mount('#app')
.container {
  width: 300px;
}
<div id="app">
  <card>
    <template v-slot:header>
      <p class="card-header-title">
        Card Header Title
      </p>
    </template>

    <template v-slot:default>
      <p>
        Lorem ipsum leo risus, porta ac consectetur ac, vestibulum at eros. Donec id elit non mi porta gravida at eget metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras mattis consectetur purus sit amet fermentum.
      </p>
    </template>

    <template v-slot:footer>
      <a href="#" class="card-footer-item">Save</a>
      <a href="#" class="card-footer-item">Edit</a>
      <a href="#" class="card-footer-item">Delete</a>
    </template>
  </card>
</div>

在这里,我们使用Bulma卡片组件的类作为基础骨架,并为每个部分(页眉、内容、页脚)添加一个槽。然后,当我们添加内容时,一切都被正确地结构化了。

见笔者
Vue 3槽。Card Component with Bulma by SitePoint (@SitePoint)
onCodePen.

继续阅读《SitePoint上的Vue插槽综合指南》。