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. 避免过度使用,简单场景优先考虑普通插槽
相关推荐
小码哥_常22 分钟前
Kotlin类型魔法:Any、Unit、Nothing 深度探秘
前端
Web极客码1 小时前
深入了解WordPress网站访客意图
服务器·前端·wordpress
幺风2 小时前
Claude Code 源码分析 — Tool/MCP/Skill 可扩展工具系统
前端·javascript·ai编程
vjmap2 小时前
唯杰地图CAD图层加高性能特效扩展包发布
前端·gis
ZC跨境爬虫2 小时前
3D 地球卫星轨道可视化平台开发 Day7(AI异步加速+卫星系列精简+AI Agent自动评论)
前端·人工智能·3d·html·json
ID_180079054732 小时前
淘宝 API 上货 / 商品搬家 业务场景实现 + JSON 返回示例
前端·javascript·json
M ? A2 小时前
Vue 动态组件在 React 中,VuReact 会如何实现?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
vipbic3 小时前
独立开发复盘:我用 Uni-app + Strapi v5 肝了一个“会上瘾”的打卡小程序
前端·微信小程序
IT_陈寒4 小时前
Vite的热更新突然失效,原来是因为这个配置
前端·人工智能·后端
ZC跨境爬虫4 小时前
3D 地球卫星轨道可视化平台开发 Day8(分步渲染200颗卫星+ 前端分页控制)
前端·python·3d·重构·html