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. 避免过度使用,简单场景优先考虑普通插槽
相关推荐
excel17 小时前
为什么需要构建工具(Webpack / Vite 的本质)
前端
lang2015092817 小时前
Java SAX 流式解析全解:从原理到 EasyExcel 实战
java·前端·javascript
VidDown17 小时前
视频协议传输全解析:从 HTTP/HTTPS 到 HLS/DASH 的完整旅程
javascript·网络·http·https·编辑器·音视频·视频编解码
Rain50917 小时前
2.4. PostgreSQL 数据库连接与实战指南
前端·数据库·人工智能·后端·postgresql·数据分析
console.log('npc')17 小时前
Codex 桌面端接入 Headroom 压缩代理完整教程
前端·vscode
独泪了无痕17 小时前
Vue集成uuid生成唯一标识实践指南
前端·vue.js
yuanyxh1 天前
Mac 软件推荐
前端·javascript·程序员
万少1 天前
AtomCode开发微信小程序《谁去呀》 全流程
前端·javascript·后端
某人辛木1 天前
Web自动化测试
前端·python·pycharm·pytest
Kagol1 天前
Superpowers GSD gstack AgentSkills深度测评
前端·人工智能