vue组件插槽

526 阅读2分钟

当组件的某一部分的内容不确定时,怎么处理?

  • 答:使用组件插槽slot

  • slot是什么?

    • slot是一个占位符。当组件的内容不确定的时候先用slot标签先占位

当有多个部分内容不确定的时候,怎么处理?

  • 答:使用具名插槽。根据插槽的名字把数据传到相应的位置。

插槽的作用

  • 可以让组件更加灵活应用。

默认插槽

  1. 创建一个组件Pannel.vue
<template>
  <div>
    <!-- 按钮标题 -->
    <div class="title">
      <h4>芙蓉楼送辛渐</h4>
      <span class="btn" @click="isShow = !isShow">
        {{ isShow ? "收起" : "展开" }}
      </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
         <!-- 插槽 -->
        <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,   //控制切换“收起”和“展开”的变量
    };
  },
};
</script>

<style scoped>
h3 {
  text-align: center;
}

.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #ccc;
  padding: 0 1em;
}

.title h4 {
  line-height: 2;
  margin: 0;
}

.container {
  border: 1px solid #ccc;
  padding: 0 1em;
}

.btn {
  /* 鼠标改成手的形状 */
  cursor: pointer;
}

img {
  width: 50%;
}
</style>
  1. 在父组件中引入Pannel组件,并注册
<script>
//引入组件,并注册组件
import Pannel from "./components/Pannel.vue";
export default {
  components: {
    Pannel
  }
}
</script>
  1. 使用组件,并传入需要显示的内容
<template>
  <div>
  <!-- 使用组件,并传入需要在插槽的位置显示的内容 -->
    <Pannel>
          <p>寒雨连江夜入吴,</p>
          <p>平明送客楚山孤。</p>
          <p>洛阳亲友如相问,</p>
          <p>一片冰心在玉壶。</p>
    </Pannel>
  </div>
</template>

具名插槽

  • slot的name属性,可以在同一个组里使用多个slot插槽
  • 在组件标签之间使用template标签,并添加v-slot:"name"属性给具名插槽添加内容
  • v-slot --> #(简写)

1、创建具名插槽组件(Pannel.vue)

<template>
  <div>
    <!-- 按钮标题 -->
    <div class="title">
      <!-- 标题插槽 -->
      <slot name="title"></slot>
      <span class="btn" @click="isShow = !isShow">
        {{ isShow ? "收起" : "展开" }}
      </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
             <!-- 主体内容插槽 -->
          <slot name="content"></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,
      }
    };
  },
};
</script>

<style scoped>
h3 {
  text-align: center;
}

.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #ccc;
  padding: 0 1em;
}

.title h4 {
  line-height: 2;
  margin: 0;
}

.container {
  border: 1px solid #ccc;
  padding: 0 1em;
}

.btn {
  /* 鼠标改成手的形状 */
  cursor: pointer;
}

img {
  width: 50%;
}
</style>

2、引入具名插槽组件,并注册

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

3、使用具名插槽组件

<template>
  <div>
    <Pannel>
      <!-- 通过template标签和v-slot给具体的插槽添加内容 -->
        <template v-slot:title>
          <h1>具名插槽</h1>
        </template>
        <template #content>
          <p>寒雨连江夜入吴,</p>
          <p>平明送客楚山孤。</p>
          <p>洛阳亲友如相问,</p>
          <p>一片冰心在玉壶。</p>
        </template>
    </Pannel>
  </div>
</template>

插槽的作用域

  • 使用场景:使用组件插槽时,需要使用子组件内的变量

  • 使用:

    • 子组件在slot标签上添加属性并赋值
    • 使用组件时,通过v-slot="变量名"获取slot标签上的属性和值

1、创建一个插槽作用域的组件(Pannel.vue)

<template>
  <div>
    <!-- 按钮标题 -->
    <div class="title">
      <!-- <h4>芙蓉楼送辛渐</h4> -->
      <slot name="title"></slot>
      <span class="btn" @click="isShow = !isShow">
        {{ isShow ? "收起" : "展开" }}
      </span>
    </div>
    <!-- 下拉内容 -->
    <div class="container" v-show="isShow">
             <!-- 使用作用域插槽 -->
          <slot name="content" :obj=defaultObj>{{defaultObj.defaultOne}}</slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isShow: false,
      //定义子组件的数据
      defaultObj:{
          defaultOne:'李狗蛋',
          defaultTwo:'张翠花'
      }
    };
  },
};
</script>

<style scoped>
h3 {
  text-align: center;
}

.title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid #ccc;
  padding: 0 1em;
}

.title h4 {
  line-height: 2;
  margin: 0;
}

.container {
  border: 1px solid #ccc;
  padding: 0 1em;
}

.btn {
  /* 鼠标改成手的形状 */
  cursor: pointer;
}

img {
  width: 50%;
}
</style>

2、引入组件,并注册

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

3、使用作用域插槽

<template>
  <div>
    <Pannel>
      <!-- 通过template标签和v-slot给具体的插槽添加内容 -->
        <template v-slot:title>
          <h1>具名插槽</h1>
        </template>
        <template #content>
          <p>寒雨连江夜入吴,</p>
          <p>平明送客楚山孤。</p>
          <p>洛阳亲友如相问,</p>
          <p>一片冰心在玉壶。</p>
        </template>
    </Pannel>
    <Pannel>
      <!-- 通过template标签和v-slot="变量"给具体的插槽的数据 -->
        <template v-slot:title>
          <h1>插槽作用域</h1>
        </template>
        <template v-slot:content="scope">
          <p>寒雨连江夜入吴,</p>
          <p>平明送客楚山孤。</p>
          <p>洛阳亲友如相问,</p>
          <p>一片冰心在玉壶。</p>
          <div>{{scope.obj.defaultTwo}}</div>
        </template>
    </Pannel>
  </div>
</template>

能不能给插槽设置默认的显示内容?

  • 可以。在slot标签之间设置需要的默认内容即可
  • 当不给插槽slot传入内容时,就会显示默认的内容
  • 传入显示内容,就覆盖默认的内容