Vue 作用域插槽

Vue 作用域插槽(Scoped Slots)学习笔记

一、核心概念

作用域插槽是 Vue 插槽的高级用法,核心解决了子组件数据向父组件插槽反向传递的问题:

  • 普通插槽:仅支持父组件向子组件传递结构,无法访问子组件内部数据
  • 作用域插槽:子组件通过"插槽 Prop"暴露内部数据,父组件接收后可自定义渲染逻辑,实现"逻辑复用+样式自定义"的灵活组合

本质上是子组件向父组件插槽传参,使插槽内容能与子组件数据联动。

二、核心差异:普通插槽 vs 作用域插槽

特性 普通插槽 作用域插槽
数据流向 父组件→子组件 子组件→父组件(插槽内)
父组件访问子组件数据 不可 可(通过插槽 Prop 接收)
典型场景 固定结构传递 动态结构渲染

三、基础实现步骤

1. 子组件:定义插槽并暴露数据

使用v-bind:属性名="数据"(简写:属性名="数据")为插槽绑定"插槽 Prop":

vue 复制代码
<!-- 子组件 List.vue -->
<template>
  <div class="list-container">
    <div v-for="(item, index) in list" :key="item.id">
      <!-- 暴露列表项、索引和激活状态 -->
      <slot :item="item" :index="index" :isActive="index === currentIndex"></slot>
    </div>
  </div>
</template>

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

const list = ref([
  { id: 1, name: 'Vue', desc: '前端框架' },
  { id: 2, name: 'React', desc: 'UI库' },
  { id: 3, name: 'Angular', desc: '全栈框架' }
])

const currentIndex = ref(0)
</script>

2. 父组件:接收插槽 Prop 并渲染

使用v-slot:插槽名="接收变量"(简写#插槽名="接收变量")接收数据:

vue 复制代码
<!-- 父组件 Parent.vue -->
<template>
  <div>
    <h3>框架列表</h3>
    <List>
      <!-- 完整写法 -->
      <template v-slot:default="slotProps">
        <div class="list-item" :class="{ active: slotProps.isActive }">
          <span>{{ slotProps.index + 1 }}. {{ slotProps.item.name }}</span>
          <p>{{ slotProps.item.desc }}</p>
        </div>
      </template>
    </List>
  </div>
</template>

3. 简化写法:解构插槽 Prop

vue 复制代码
<List>
  <!-- 解构写法 -->
  <template #default="{ item, index, isActive }">
    <div class="list-item" :class="{ active: isActive }">
      <span>{{ index + 1 }}. {{ item.name }}</span>
      <p>{{ item.desc }}</p>
    </div>
  </template>
</List>

四、进阶用法:具名作用域插槽

1. 子组件定义多个插槽

vue 复制代码
<!-- 子组件 Card.vue -->
<template>
  <div class="card">
    <slot name="title" :title="cardTitle"></slot>
    <slot name="content" :content="cardContent" :author="author"></slot>
    <slot name="footer" :isLike="isLike" @toggleLike="toggleLike"></slot>
  </div>
</template>

2. 父组件针对性接收数据

vue 复制代码
<Card>
  <template #title="{ title }">
    <h2 class="card-title">{{ title }}</h2>
  </template>
  
  <template #content="{ content, author }">
    <p class="card-content">{{ content }}</p>
    <p class="card-author">作者:{{ author }}</p>
  </template>
  
  <template #footer="{ isLike, toggleLike }">
    <button @click="toggleLike">
      {{ isLike ? '已点赞' : '点赞' }}
    </button>
  </template>
</Card>

五、实用技巧

1. 默认插槽简写

vue 复制代码
<!-- 简写前 -->
<List>
  <template #default="{ item }">{{ item.name }}</template>
</List>

<!-- 简写后 -->
<List #="{ item }">
  <span>{{ item.name }}</span>
</List>

2. 插槽 Prop 重命名

vue 复制代码
<List #="{ item: frameworkItem }">
  <span>{{ frameworkItem.name }}</span>
</List>

3. 设置默认值

vue 复制代码
<List #="{ item = { name: '默认框架', desc: '无描述' } }">
  <span>{{ item.name }}</span>
  <p>{{ item.desc }}</p>
</List>

六、典型应用场景

  1. 列表组件:子组件处理数据获取和分页,父组件自定义项样式
  2. 表格组件:子组件管理表格结构,父组件定制单元格内容
  3. 容器组件:子组件提供基础结构和状态,父组件定义内容
  4. 通用组件:适应多种场景的可复用组件

七、注意事项

  1. 插槽 Prop 仅在该插槽模板内有效
  2. 避免过度使用,简单场景优先考虑普通插槽
相关推荐
ohyeah1 天前
深入理解 React 中的 useRef:不只是获取 DOM 元素
前端·react.js
MoXinXueWEB1 天前
前端页面获取不到url上参数值
前端
低保和光头哪个先来1 天前
场景6:对浏览器内核的理解
开发语言·前端·javascript·vue.js·前端框架
想要一只奶牛猫1 天前
Spring Web MVC(三)
前端·spring·mvc
+VX:Fegn08951 天前
计算机毕业设计|基于springboot + vueOA工程项目管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
奋飛1 天前
微前端系列:核心概念、价值与应用场景
前端·微前端·micro·mfe·什么是微前端
ji_shuke1 天前
canvas绘制拖拽箭头
开发语言·javascript·ecmascript
2501_946244781 天前
Flutter & OpenHarmony OA系统设置页面组件开发指南
开发语言·javascript·flutter
cz追天之路1 天前
华为机考 ------ 识别有效的IP地址和掩码并进行分类统计
javascript·华为·typescript·node.js·ecmascript·less·css3
进击的野人1 天前
Vue Router 深度解析:从基础概念到高级应用实践
前端·vue.js·前端框架