插槽(Slots)

 前端   大苹果   2024-09-17 10:18   172

在 Vue 3 中,setup 函数中处理插槽(Slots)与 Vue 2 中插槽的使用方式有一些不同,尤其是在处理具名插槽和作用域插槽时。Vue 3 通过 Composition API 和 setup 函数使插槽的管理更加灵活和简洁。

本文将详细介绍如何在 Vue 3 中使用默认插槽、具名插槽和作用域插槽,并通过实例讲解如何在 setup 函数中使用这些插槽。

一、Vue 3 插槽基础概念

插槽(Slots)是 Vue 中用于在子组件中插入动态内容的机制。父组件可以在子组件的插槽中传递 HTML 模板片段或数据。

1. 默认插槽

默认插槽用于在不具名的情况下,将父组件的内容插入到子组件的插槽位置。

2. 具名插槽

具名插槽允许我们定义多个插槽,每个插槽都可以有一个名称,父组件可以选择向指定插槽传递内容。

3. 作用域插槽

作用域插槽允许子组件将数据暴露给父组件,父组件可以根据这些数据来决定如何渲染插槽中的内容。

二、默认插槽的使用

默认插槽用于父组件向子组件传递内容,而不需要具名。

1. 父组件使用默认插槽

<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <p>这是传递给子组件的内容</p>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
};
</script>

2. 子组件接收默认插槽

在子组件中,我们可以通过 <slot> 标签来占位,表示父组件传递的内容将在此处被插入。

<template>
  <div>
    <h2>子组件</h2>
    <slot></slot> <!-- 父组件传递的内容将插入到这里 -->
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
};
</script>

三、具名插槽的使用

具名插槽允许父组件通过指定的插槽名称来传递不同的内容。

1. 父组件使用具名插槽

<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <template v-slot:header>
        <h3>这是标题部分</h3>
      </template>
      <template v-slot:footer>
        <p>这是页脚部分</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
};
</script>

2. 子组件接收具名插槽

子组件通过 v-slot 指令或 <slot name> 来接收不同名称的插槽内容。

<template>
  <div>
    <h2>子组件</h2>
    <div class="header">
      <slot name="header"></slot> <!-- 具名插槽 "header" -->
    </div>
    <div class="footer">
      <slot name="footer"></slot> <!-- 具名插槽 "footer" -->
    </div>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
};
</script>

四、作用域插槽的使用

作用域插槽允许子组件将内部的数据暴露给父组件,父组件根据这些数据决定如何渲染插槽内容。

1. 父组件使用作用域插槽

在父组件中,我们通过 v-slot 接收子组件暴露的参数,并可以动态渲染内容。

<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <template v-slot:default="slotProps">
        <p>来自子组件的数据:{{ slotProps.info }}</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
};
</script>

2. 子组件暴露数据给作用域插槽

子组件通过 <slot> 标签暴露数据给父组件。在 Vue 3 的 setup 中,我们可以通过 slots.default 来使用插槽。

<template>
  <div>
    <h2>子组件</h2>
    <slot :info="message"></slot> <!-- 暴露数据给父组件 -->
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  setup() {
    const message = 'Hello from Child Component';
    return { message };
  }
});
</script>

五、在 setup 中使用插槽

在 Vue 3 的 setup 函数中,插槽通过 context.slots 来访问。我们可以使用 slots.default() 来渲染默认插槽内容,或者通过 slots.[name]() 来渲染具名插槽。

1. 默认插槽在 setup 中的使用

<template>
  <div>
    <h2>子组件</h2>
    <div>
      <slot></slot> <!-- 这里会插入默认插槽内容 -->
    </div>
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  setup(props, { slots }) {
    return () => (
      <div>
        <h2>子组件</h2>
        <div>{ slots.default ? slots.default() : '无内容' }</div>
      </div>
    );
  }
});
</script>

2. 具名插槽在 setup 中的使用

<template>
  <div>
    <slot name="header"></slot> <!-- 渲染 header 插槽 -->
    <div>主体内容</div>
    <slot name="footer"></slot> <!-- 渲染 footer 插槽 -->
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  setup(props, { slots }) {
    return () => (
      <div>
        <div>{ slots.header ? slots.header() : '默认头部' }</div>
        <div>主体内容</div>
        <div>{ slots.footer ? slots.footer() : '默认尾部' }</div>
      </div>
    );
  }
});
</script>

六、作用域插槽在 setup 中的使用

<template>
  <div>
    <slot :info="info"></slot> <!-- 将子组件数据暴露给父组件 -->
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  setup() {
    const info = '从子组件传递的作用域数据';
    return { info };
  }
});
</script>

在父组件中,可以通过 v-slot 指令接收并使用子组件暴露的 info 数据:

<template>
  <div>
    <ChildComponent v-slot="{ info }">
      <p>父组件接收到的作用域数据:{{ info }}</p>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
};
</script>

总结

  1. 默认插槽:通过 <slot> 标签使用,父组件可以向子组件传递内容。
  2. 具名插槽:通过 v-slot:[name] 指令使用,允许在子组件内定义多个插槽位置。
  3. 作用域插槽:子组件可以暴露数据给父组件,父组件根据暴露的数据动态渲染内容。
  4. setup 中使用插槽:通过 context.slots 获取插槽内容,结合 JSX 或渲染函数可以灵活渲染插槽。

Vue 3 的插槽机制相比 Vue 2 更加灵活,在 setup 中使用插槽和暴露数据使得组件通信更加简洁。