Vue 插槽(solt)的使用方法及使用场景总结

在 Vue 中,插槽(slot)是一种强大的机制,用于在父组件中将内容传递到子组件的特定位置。Vue 插槽有助于实现组件内容的灵活性和复用性。

插槽的使用方法

  • 基本插槽:基本插槽用于在父组件中向子组件传递内容。
//子组件(MyComponent.vue)
<template>
  <div class="my-component">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'MyComponent'
}
</script>

<style scoped>
.my-component {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>
//父组件
<template>
  <div>
    <MyComponent>
      <p>This is some content from the parent component.</p>
    </MyComponent>
  </div>
</template>

<script setup>
import MyComponent from './MyComponent.vue'
</script>
  • 具名插槽:具名插槽允许在子组件中定义多个插槽,每个插槽有一个名称。
//子组件
<template>
  <div class="my-component">
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script>
export default {
  name: 'MyComponent'
}
</script>

<style scoped>
.my-component {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>
//父组件
<template>
  <div>
    <MyComponent>
      <template #header>
        <h1>Header Content</h1>
      </template>
      <p>Main Content</p>
      <template #footer>
        <footer>Footer Content</footer>
      </template>
    </MyComponent>
  </div>
</template>

<script setup>
import MyComponent from './MyComponent.vue'
</script>

  • 作用域插槽:作用域插槽允许父组件访问子组件的数据,并根据这些数据渲染内容。
//子组件
<template>
  <div class="my-component">
    <slot :item="item"></slot>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

const item = reactive({
  name: 'Vue.js',
  version: '3.0'
})
</script>

<style scoped>
.my-component {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>

//父组件
<template>
  <div>
    <MyComponent v-slot="{ item }">
      <p>Name: {{ item.name }}</p>
      <p>Version: {{ item.version }}</p>
    </MyComponent>
  </div>
</template>

<script setup>
import MyComponent from './MyComponent.vue'
</script>

使用场景

  • 内容分发和复用:插槽可以让父组件将不同的内容插入到子组件中,提升组件的复用性。例如,一个通用的对话框组件可以使用插槽插入不同的标题和内容。
  • 组件之间的解耦:插槽让父组件和子组件之间的依赖关系更松散,子组件无需知道父组件提供的具体内容。
  • 灵活的布局:通过具名插槽,父组件可以灵活地控制子组件内部的布局。例如,一个布局组件可以使用具名插槽定义不同区域(头部、内容区、底部)的内容。
  • 数据传递:作用域插槽让父组件可以访问子组件的数据,适用于需要根据子组件数据动态渲染内容的场景。

插槽的高级用法

  • 默认插槽内容:子组件可以定义默认的插槽内容,当父组件未提供内容时显示
//子组件
<template>
  <div class="my-component">
    <slot>This is default content</slot>
  </div>
</template>

<script setup>
</script>

<style scoped>
.my-component {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>
  • 动态插槽名:可以使用动态插槽名来决定渲染哪个插槽。
//子组件
<template>
  <div class="my-component">
    <slot :name="dynamicSlot"></slot>
  </div>
</template>

<script setup>
import { toRefs } from 'vue'

const props = defineProps({
  dynamicSlot: {
    type: String,
    required: true
  }
})
</script>

<style scoped>
.my-component {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>
//父组件
<template>
  <div>
    <MyComponent :dynamicSlot="currentSlot">
      <template #slotA>
        <p>This is Slot A</p>
      </template>
      <template #slotB>
        <p>This is Slot B</p>
      </template>
    </MyComponent>
    <button @click="currentSlot = 'slotA'">Show Slot A</button>
    <button @click="currentSlot = 'slotB'">Show Slot B</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import MyComponent from './MyComponent.vue'

const currentSlot = ref('slotA')
</script>

总结

Vue 插槽提供了灵活且强大的方式来构建可复用和动态的组件。无论是简单的内容分发还是复杂的数据传递和布局控制,插槽都能很好地满足这些需求。在 Vue 3 中,插槽的使用变得更加简洁和直观,通过结合 Composition API,可以更好地管理组件的逻辑和状态。

完整实例代码

<!-- 默认插槽用于传递组件中的默认内容,适用于简单的内容传递。 -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Default Slot Example</title>
    <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.prod.js"></script>
</head>

<body>
    <div id="app">
        <default-slot-example>
            <p>这是一个默认插槽!!!</p>
        </default-slot-example>
    </div>

    <script>
        const DefaultSlotExample = {
            template: `
        <div>
          <h1>Default Slot Example</h1>
          <slot></slot>
        </div>
      `
        };

        const app = Vue.createApp({
            components: {
                DefaultSlotExample
            }
        });

        app.mount('#app');
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Named Slot Example</title>
    <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.prod.js"></script>
</head>

<body>
    <div id="app">
        <named-slot-example>
            <template v-slot:header>
                <h1>This is header content</h1>
            </template>
            <template v-slot:footer>
                <p>This is footer content</p>
            </template>
        </named-slot-example>
    </div>

    <script>
        const NamedSlotExample = {
            template: `
        <div>
          <header>
            <slot name="header"></slot>
          </header>
          <main>
            <p>Main content goes here</p>
          </main>
          <footer>
            <slot name="footer"></slot>
          </footer>
        </div>
      `
        };

        const app = Vue.createApp({
            components: {
                NamedSlotExample
            }
        });

        app.mount('#app');
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Scoped Slot Example</title>
    <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.prod.js"></script>
</head>

<body>
    <div id="app">
        <scoped-slot-example>
            <template v-slot:default="slotProps">
                <p>User: {{ slotProps.user.name }}</p>
                <p>Age: {{ slotProps.user.age }}</p>
            </template>
        </scoped-slot-example>
    </div>

    <script>
        const ScopedSlotExample = {
            template: `
        <div>
          <slot :user="user"></slot>
        </div>
      `,
            data () {
                return {
                    user: {
                        name: 'Alice',
                        age: 25
                    }
                };
            }
        };

        const app = Vue.createApp({
            components: {
                ScopedSlotExample
            }
        });

        app.mount('#app');
    </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值