Vue快速上手:七、插槽

上一章讲了组件将JS中的状态值传其它组件,但是如果是需要传模板内容(HTML代码)传给子组件来达到灵活使用组件的功能, 要实现这一功能就不得不说一下插槽了。

基本使用

使用方法:

  • 父组件直接在子组件标签写模板内容,类似在HTML中嵌套HTML代码一样。
  • 在子组件使用输出。

如:

子组件:

xml 复制代码
<script setup>
    const props = defineProps({
        v: String
    })
</script>

<template>
    <div class="form-input-box">
        <div class="form-input-lable">
            <slot></slot> <!-- 在引输入父组件的插槽内容 -->
        </div>
        <div class="form-input">
            <input type="text" v-model="props.v">
        </div>
    </div>
</template>

<style scoped>
    .form-input-box {
        margin: 20px 0 0;
        width: 500px;
        background-color: aquamarine;
    }
    .form-input-lable {
        display: flex;
        justify-content: space-between;
    }
    input {
        width: 100%;
    }
</style>

父组件:

xml 复制代码
<script setup>
    import { reactive } from "vue";
    import MyInput from "@/components/MyInput.vue";

    // 声明响应式状态数据
    const data = reactive({
        name: "",
        xx: "",
        love: ""
    })
</script>

<template>

    <!--  input1  -->
    <MyInput :v="data.name"> <!-- 组件标签内部嵌套的部分就是插槽内容 -->
        <label>姓名</label>
    </MyInput>

    <!-- input2 -->
    <MyInput :v="data.xx"> <!-- 组件标签内部嵌套的部分就是插槽内容 -->
        <label>血型</label>
        <span>A、B、O、AB</span>
    </MyInput>
</template>

页面上生成的HTML结构就为:

javascript 复制代码
<div data-v-f33d1cc8="" class="form-input-box">
    <div data-v-f33d1cc8="" class="form-input-lable">
        <label>姓名</label> <!-- 插槽的内容原样输出在这里 -->
    </div>
    <div data-v-f33d1cc8="" class="form-input">
        <input data-v-f33d1cc8="" type="text">
    </div>
</div>

<div data-v-f33d1cc8="" class="form-input-box">
    <div data-v-f33d1cc8="" class="form-input-lable"><!-- 组件标签内部嵌套的部分就是插槽内容 -->
        <label>血型</label>
        <span>A、B、O、AB</span> <!-- 插槽的内容原样输出在这里 -->
    </div>
    <div data-v-f33d1cc8="" class="form-input">
        <input data-v-f33d1cc8="" type="text">
    </div>
</div>

插槽默认内容

在外部没有提供任何内容的情况下,可以为插槽指定默认内容。比如:如果我们想在父组件没有提供任何插槽内容时在 <button> 内渲染"Submit",只需要将"Submit"写在 <slot> 标签之间来作为默认内容:

xml 复制代码
<button type="submit"> 
    <slot> Submit <!-- 默认内容 --> </slot> 
</button>

具名插槽

一个组件的插槽是可以有多个的,不过需要为每个插槽命名,才知道每一次要渲染的内容。这种带命名的插槽就是具名插槽,像前面的那种没有命名的就是默认插槽,只不过默认插槽会有一个隐式的名称default;

使用方法:

  • 在父组件使用template包含插槽内容,并在template添加v-slot:插槽名指令为其命名, 同样使用可用简写#插槽名
  • 子组件的slot中使用name属性来渲染对就插槽的内容。

父组件:

xml 复制代码
<script setup>
    import Container from "@/components/Container.vue";
</script>

<template>
    <Container>
        <template v-slot:header> <!-- 使用v-slot具名为 header -->
            <div class="header">这是头部</div>
        </template>

        <template #default> <!-- 这里为默认插槽 -->
            <div class="main">这是中间部分,使用的是默认插槽</div>
        </template> 

        <template #footer> <!-- 使用简写为其具名 -->
            <div class="footer">这是底部</div>
        </template>
    </Container>
</template>

子组件:

xml 复制代码
<template>
    <section>
        <slot name="header"></slot> <!-- 渲染header插槽 -->
        <slot></slot> <!-- 渲染默认插槽 -->
        <slot name="footer"></slot> <!-- 渲染footer插槽 -->
    </section>
</template>

作用域插槽(在插槽中传值)

一般情况下插槽的内容只能使用父组件中的状态数据,因为插槽的内容都是在父组件中定义的,使用状态数据也只能使用父组件定义的,但是我们可以像对组件传递props那样,向一个插槽的出口上传递属性值:

子组件中:

xml 复制代码
<script setup>
    import { ref } from "vue";
    const msg = ref("插槽学习");
</script>
<template>
    <section>
        <slot :msg="msg"></slot> <!-- 将msg传给插槽 -->
    </section>
</template>

父组件中

xml 复制代码
<script setup>
    import Container from "@/components/Container.vue";
</script>

<template>
    <Container v-slot="slotProps"> <!-- 自定义一个名称接收插槽传来的属性值 -->
        <p>{{ slotProps.msg }}</p> <!-- 使用属性msg -->
    </Container>
</template>

条件插槽

有时你需要根据插槽是否存在来渲染某些内容时,可以结合使用 $slot 属性与v-if来实现。

父组件:

xml 复制代码
<script setup>
    import Container from "@/components/Container.vue";
</script>

<template>
    <Container>
        <template #header>
            <div class="header">header</div>
        </template>
        
        <template #default>
            <div class="main">main</div>
        </template>
        
        <template #footer>
            <div class="footer">footer</div>
        </template>
    </Container>
</template>

子组件:

xml 复制代码
<template>
    <div class="conainter">
        <slot v-if="$slots.header" name="header"></slot> <!--如果存在header插槽就渲染-->
        <slot v-if="$slots.default" name="default"></slot> <!--如果存在默认插槽就渲染-->
        <slot v-if="$slots.footer" name="footer"></slot> <!--如果存在footer插槽就渲染-->
    </div>
</template>

动态插槽

动态插槽就是动态的命名具名插槽,在不同的情况下使用不同命名的插槽。

结合上的条件插槽,以下面这个例子来介绍什么是动态插槽:

父组件:

xml 复制代码
<script setup>
import { ref } from "vue";
    import Container from "@/components/Container.vue";

    const slotListNames = ['header', 'default', 'footer'];
    const curSlotName = ref(slotListNames[0]);

    //获取数组索引内的随机数
    const getRandomIndex = (arr) => parseInt(Math.random() * slotListNames.length);
    // 更新插槽名
    const handleChang = () => {
        curSlotName.value = slotListNames[getRandomIndex()];
    }
</script>

<template>
    <Container>
        <template #[curSlotName]>
            <div v-if="curSlotName === 'default' ">
                这是默认插槽的内容
            </div>

            <div v-if="curSlotName === 'header'">
                这是header插槽的内容
            </div>

            <div v-if="curSlotName === 'footer'">
                这是footer插槽的内容
            </div>
        </template>
    </Container>

    <button @click="handleChang">更新插槽名</button>
</template>

子组件:

xml 复制代码
<template>
    <div class="conainter">
        <slot v-if="$slots.header" name="header"></slot> <!--如果存在header插槽就渲染-->
        <slot v-if="$slots.default" name="default"></slot> <!--如果存在默认插槽就渲染-->
        <slot v-if="$slots.footer" name="footer"></slot> <!--如果存在footer插槽就渲染-->
    </div>
</template>

到此Vue快速入门的基础知识也讲得差不多了,下一章节将会通过完成一个简单的任务管理器来综合的运用这些知识。

相关推荐
bin91532 小时前
DeepSeek 助力 Vue 开发:打造丝滑的文本输入框(Text Input)
前端·javascript·vue.js·前端框架·ecmascript·deepseek
B站计算机毕业设计超人3 小时前
计算机毕业设计SpringBoot+Vue.jst网上超市系统(源码+LW文档+PPT+讲解)
vue.js·spring boot·后端·eclipse·intellij-idea·mybatis·课程设计
前端没钱4 小时前
日报列表滚动到哪里、哪里就自动变成已读状态
前端·vue.js
想尝一尝被打赏的味道4 小时前
uniapp在app下使用mqtt协议!!!支持vue3
javascript·vue.js·uni-app
cc.ChenLy5 小时前
vue框架后遗症∶被遗忘的dom操作
javascript·vue.js
❆VE❆5 小时前
vue3: directive自定义指令防止重复点击
前端·javascript·vue.js·自定义指令·directive
巴巴博一6 小时前
vue-i18n国际化插件安装教程(Vue3篇)
前端·javascript·vue.js·typescript
剑走偏锋o.O8 小时前
Vue.js 学习笔记:TodoList 待办事项小案例
vue.js·笔记·学习
qq_12498707539 小时前
SpringBoot+Vue+微信小程序的猫咖小程序平台(程序+论文+讲解+安装+调试+售后)
vue.js·微信小程序·小程序·毕业设计
祈澈菇凉13 小时前
什么是 Vue 的自定义事件?如何触发和监听?
前端·javascript·vue.js