vue中的插槽

65 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 

1.什么是插槽?

插槽的关键字slot,默认情况下,组件中的模板会覆盖组件中的原始内容(即自定义标签对内部的内容会不显示)

组件的原始内容: 即在vue实例范围之内,因此可以调用实例的data和methods

好处:让组件使用更灵活, 功能更强大, 复用性更强,让组件内的部分标签支持自定义

使用场景:比如布局组件、表格列、下拉选、弹框显示内容等

比如我们项目中经常会使用到一个多处复用的组件,但是在每个地方使用时,都需要一些细微的更改,只需使用插槽向需要微调的位置传递内容,就能让这个组件在不同场景下应用

简单说就是可以对复用组件的私人定制!

2.插槽的分类

插槽总共分为三类:

匿名插槽

具名插槽

作用域插槽

3.默认插槽

默认插槽就是指没有名字的插槽,子组件未定义的名字的插槽,父级将会把指定插槽的填充的内容填充到默认插槽中

default,可以省略default直接写v-slot

先上效果:

1.png

  1. 在子组件中使用 占位
<template>
    <div>
        <h3>世界各地菠萝价格</h3> 
        <img src="./菠萝.png">
        <slot></slot>
    </div>
</template>
<style>
img {
    width: 5%;
    height: 5%;
}
</style>

2.在父组件中给这个占位符填充内容

<template>
  <div>
    <div>
      <Son> <div>缅甸88一斤</div></Son>
      <Son><div>泰国99一斤</div></Son>
    </div>
  </div>
</template>

<script>
import Son from "./Son.vue";
export default {
  components: { Son },
};
</script>

4.具名插槽

具名插槽其实就是给插槽取个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。可以让组件内有多处自定义标签的能力

如果slot没有name属性,就是默认插槽,而父组件中不指定slot属性的内容,就会被丢到匿名插槽中。

v-slot可以简写为 #,但是必须写参数

1. 在子组件中使用 占位, 并设置 name 属性

<template>
  <div>
    <h3>世界各地菠萝价格</h3>
    <img src="../菠萝.png" />
    <slot name="noe"></slot>
    <slot name="two"></slot>
  </div>
</template>
<style>
img {
  width: 5%;
  height: 5%;
}
</style>

2. 在父组件中给这个占位符填充内容

<template>
 <div>
<Son> 
<div slot="noe">
 缅甸88一斤!真好吃 
</div>
</Son>
<Son>
  <div slot="two">
 泰国99一斤 
</div>
</Son>
</div>
</template>
<script>
import Son from "./Son.vue";
export default {
  components: { Son },
};
</script>

5.作用域插槽

作用域插槽就是带数据的插槽

可以在使用组件时访问组件内的数据

子组件在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件v-slot接受的对象上

先上效果图:

2.png 使用方法

1. 在子组件中使用 占位, 并使用 v-bind 绑定数据给 slot 标签

<template>
  <div>
    <table border="1">
      <thead>
        <tr>
          <th>序号</th>
          <th>品名</th>
          <th>图片</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in arr" :key="item.id">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td><slot name="one"></slot></td>
          <td>
            <!-- 定义插槽 -->
            <slot :row="item"></slot>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  props: { arr: Array },
};
</script>
<style scoped>
td {
  height: 70px;
}
</style>

2. 父组件使用组件时, 在 标签上使用 v-slot="变量名" 取值使用

<template>
  <div>
    <Son :arr="list">
      <!-- 具名插槽传递图片 -->
      <template slot="one">
        <img src="../菠萝.png" width="60px" />
      </template>
      <!-- 传递button展示 -->
      <template v-slot="scope">
        <button @click="del(scope.row.id)">删除</button>
      </template>
    </Son>
  </div>
</template>
<script>
import Son from "./Son.vue";
export default {
  components: {
    Son,
  },
  data() {
    return {
      list: [
        {
          id: "1",
          name: "小菠萝",
        },
        {
          id: "2",
          name: "中菠萝",
        },
        {
          id: "3",
          name: "大菠萝",
        },
      ],
    };
  },
  methods: {
    del(id) {
      alert(id);
    },
  },
};
</script>