vue插槽

180 阅读2分钟

vue 插槽有什么用?插槽的本质是什么?

  1. 设计插槽的目的是什么?
  2. 插槽的使用?
  3. 插槽的有哪几种?
  4. 插槽的本质是什么?

设计目的

  • 插槽的设计目的是为了使组件的复用性更高,更灵活。通过插槽,可以在组件内部插入自定义的内容,从而实现组件的复用。

插槽的使用

  • 插槽的使用分为默认插槽、具名插槽(包含 作用域插槽) 。

默认插槽

  • 默认插槽是指在组件内部没有指定名称的插槽,可以在组件内部使用<slot></slot>标签来定义默认插槽。在组件外部使用组件时,可以在组件标签内部插入自定义的内容,这些内容会替换组件内部的默认插槽。
<!-- 组件内部 -->
<template>
  <div>
    <slot></slot>
  </div>
</template>

<!-- 组件外部 -->
<template>
  <div>
    <my-component>
      <p>这是默认插槽的内容</p>
    </my-component>
  </div>
</template>

具名插槽

  • 具名插槽是指在组件内部指定名称的插槽,可以在组件内部使用<slot name="slotName"></slot>标签来定义具名插槽。在组件外部使用组件时,可以在组件标签内部使用<template v-slot:slotName>标签来插入自定义的内容,这些内容会替换组件内部的具名插槽。
<!-- 组件内部 -->
<template>
  <div>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<!-- 组件外部 -->
<template>
  <div>
    <my-component>
      <template v-slot:header>
        <h1>这是头部插槽的内容</h1>
      </template>
      <p>这是默认插槽的内容</p>
      <template v-slot:footer>
        <p>这是底部插槽的内容</p>
      </template>
    </my-component>
  </div>
</template>

作用域插槽

  • 作用域插槽是指在组件内部使用<slot :data="data"></slot>标签来定义作用域插槽,其中data是组件内部的数据。在组件外部使用组件时,可以在组件标签内部使用<template v-slot:slotName="slotProps">标签来插入自定义的内容,其中slotProps是组件内部的数据,可以在自定义内容中使用。
<!-- 组件内部 -->
<template>
  <div>
    <slot :data="data"></slot>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        data: [1, 2, 3, 4, 5],
      };
    },
  };
</script>

<!-- 组件外部 -->
<template>
  <div>
    <my-component>
      <template v-slot:default="slotProps">
        <ul>
          <li v-for="item in slotProps.data" :key="item">{{ item }}</li>
        </ul>
      </template>
    </my-component>
  </div>
</template>

插槽的本质

  • 就是一个函数,通过函数的参数传递不同的内容
<template>
  <div>
    <!-- 定义插槽,传递的内容就要显示在插槽之中 -->
    <slot></slot>
    <slot name="menu"></slot>
    <slot name="menu1" msg="hello"></slot>
  </div>
</template>
<script>
/**
 * 插槽的作用: 就是组件的复用,通过插槽可以传递不同的内容,实现组件的复用。
 * 插槽: 1. 默认插槽 2. 具名插槽 3. 作用域插槽
 * 本质: 就是一个函数,通过函数的参数传递不同的内容
 *  <slot></slot>  这样写相当于 就在调用 default() 这个函数而已, 拿到这个虚拟节点,然后渲染到插槽之中
 *  {
 *    default: function() {}
 *    menu: function() {}
 *   menu1: function(scope) {}
 *  }
 *  slots对象: slots 用于访问组件传入的内容插槽。
 */
import { h } from "vue";
export default {
  setup(props, { slots }) {
    console.log("test slots ", slots);
    const defaultVnodes = slots.default();
    const menuVnodes = slots.menu();
    const menu1Vnodes = slots.menu1({ msg: "hello" });
    console.log("menu1Vnodes", menu1Vnodes);
    return () => {
      return h("div", null, [...defaultVnodes, ...menuVnodes, ...menu1Vnodes]);
    };
  },
};
</script>

1739239570483.png