_
2023/8/31 08:27:411037

这节课我们继续来学习插槽,经过上节课的学习,我们初步了解了插槽的作用和简单的使用,这节课先来给大家补充一些插槽的基本概念。

<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/>

好,这节课到此结束。

视频讲解