_
2023/8/31 08:27:411035

这节课我们来学习的还是插槽的知识点,主要学习内容是动态插槽名和作用域插槽。

我们接着上节课的代码来编写哈。

<script>
  const app = Vue.createApp({
    data() {
      return {
        message: "hello world!"
      }
    },
    template: `<div>
      <Shop>
          <template #shopName>福乐家购物商店</template>
          <span>我是店员小红</span>
          <template #goodsList>
            <div>
              <p>本店销售以下商品</p>
              <ol>
                <li>咖啡</li>
                <li>可乐</li>
                <li>泡面</li>
              </ol>
            </div>
          </template>
      </Shop>
    </div>`
  })


  app.component("Shop",{
    template:`
      <div>
        <h2>
          <slot name="shopName" />
        </h2>
        <div>
          <slot />
        </div>
        <div>
           <slot name="goodsList"/>
        </div>
      </div>
    `
  })


  const vm = app.mount("#app")
</script>

动态插槽名

上节课我们学习到了具名插槽,就是给插槽取个名字,让插槽内容能够对号入座,在设置插槽内容时我们通过在 v-slot:插槽名 来传递内容给指定插槽,这里的插名其实是可以设置成动态的,可以用一个变量来设置插槽名,也可以通过修改变量值来实现动态切换插槽名。

const app = Vue.createApp({
    data() {
      return {
        slotName1:"shopName",
        slotName2: "goodsList"
      }
    },
    template: `<div>
      <Shop>
          <template v-slot:[slotName1]>福乐家购物商店</template>
          <span>我是店员小红</span>
          <template #[slotName2]>
            <div>
              <p>本店销售以下商品</p>
              <ol>
                <li>咖啡</li>
                <li>可乐</li>
                <li>泡面</li>
              </ol>
            </div>
          </template>
      </Shop>
    </div>`
  })

像我们这里这样的写法,使用了两个变量slotName1 slotName2的值来设置插槽名。

作用域插槽

在某些场景下插槽的内容可能想要同时使用父组件和子组件的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。

我们来举个例子,我们先删除掉多余的代码,再来写一个商品列表组件,代码如下:

<script>
  const app = Vue.createApp({
    data() {
      return {
        message: "hello world!"
      }
    },
    template: `
      <div>
        <goods-list/>
      </div>
    `
  })

  app.component("goodsList",{
    data(){
      return {
        list:["咖啡","可乐","泡面"]
      }
    },
    template:`
    <div>
      <p>本店销售以下商品</p>
      <div v-for="(item,index) of list" :key="index" >{{item}}</div>
    </div>
    `
  })

  const vm = app.mount("#app")
</script>

目前我们用 v-for 来遍历了一个div得到了一个列表,但是在某些情况下,我们可能需要自定义列表项,比如我们想修改列表项里面的排版或者样式,但是我们goodsList组件里面又给我们固定写死了,没办法修改。如果想要实现这样需求,我们就可以用到插槽了。

我们直接用v-for来遍历一个插槽。

<slot v-for="(item,index) of list" :key="index" >{{item}}</slot>

然后就可以到父组件里面来自定列表项模版了

<goods-list>  
    <div>xxx</div>
</goods-list>

现在到浏览器看 应该是可以看到三行xxx,我们只需要把xxx替换列表数据是不是就行了呢,那列表数据它是goodsList组件内部,我们需要怎么拿呢?其实也简单,我们可以在goodsList组件内部<slot> 上把数据传出去,直接通过自定义属性的方式把值传出去。

<slot v-for="(item,index) of list" :key="index" :item="item" ></slot>

然后父组件里面通过v-slot声明一个自定变量就可以把数据取出来,取出来之后把值插入到模版里就行了。

<goods-list v-slot="props"> 
    <div style="color:pink">{{props.item}}</div>
</goods-list>

这样我们就可以实现一个可自定义列表项的商品列表,顺便我还把字体颜色给改成了猛男粉。

具名作用域插槽

上面我们演示案例中,都是通过默认插槽来实现的,具名插槽略微有点不一样。

先给插槽取个名listItem 传值的方式是一样的。

 <slot name="listItem" v-for="(item,index) of list" :key="index" :item="item" ></slot>

取值的方式有点不一样,我们需要使用v-slot先来指定插槽名称后面来自定义变量props变量接口数据。

<goods-list >
   <template v-slot:listItem="props">
      <div style="color:pink">{{props.item}}</div>
   </template>  
</goods-list>

优化商品列表

插槽的内容我们算是学习完了,我可以根据学过知识点来优化一下这个商品列表组件。

我们学过插槽默认内容,这样我们就要给列表设置一个默认列表项模版,当我们没有自定义列表项需求的时候让它显示默认的模版。

<slot name="listItem" v-for="(item,index) of list" :key="index" :item="item" >
    <div>{{item}}</div>
</slot>

当我们需要自定义列表项的时候,我们只需要在给它传入一个name为listItem的插槽模版就可以了

<goods-list >
  <div style="color:pink">{{props.item}}</div>
</goods-list>
视频讲解