当前位置: 首页 > article >正文

vue-09(使用自定义事件和作用域插槽构建可重用组件)

实践练习:使用自定义事件和作用域插槽构建可重用组件

构建可重用的组件是高效 Vue.js 开发的基石。本课重点介绍如何通过自定义事件和范围插槽来增强组件的可重用性,从而实现更灵活和动态的组件交互。我们将探索如何定义和发出自定义事件,使子组件能够与它们的父组件通信。此外,我们将深入研究 scoped slots,这是一种强大的机制,用于为组件提供模板,同时保持对组件内部数据的访问。通过掌握这些技术,您将能够创建适应性强且可维护的组件,这些组件可以轻松集成到应用程序的各个部分。

自定义事件:发出和处理

自定义事件允许子组件与其父组件通信。对于子组件需要发出状态更改信号或向其父组件请求作的场景,这种通信至关重要。

使用 $emit 发出自定义事件

$emit 方法在组件中用于触发自定义事件。$emit 的第一个参数是事件的名称,后续参数是要与事件一起传递的任何数据。

<template><button @click="handleClick">Click me</button>
</template><script>
export default {methods: {handleClick() {this.$emit('custom-event', { message: 'Hello from child!' });}}
};
</script>

在此示例中,单击按钮时,将调用 handleClick 方法。然后,此方法发出一个名为 custom-event 的自定义事件,将包含消息的对象作为数据传递。

处理父组件中的自定义事件

父组件可以使用 v-on(或其简写 @)监听其子组件发出的自定义事件。事件处理程序可以是父组件中定义的方法,也可以是内联表达式。

<template><div><child-component @custom-event="handleCustomEvent"></child-component><p>Message from child: {{ message }}</p></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {message: ''};},methods: {handleCustomEvent(eventData) {this.message = eventData.message;}}
};
</script>

在这里,父组件监听 ChildComponent 发出的自定义事件 。触发事件时,将调用 handleCustomEvent 方法,该方法使用从子对象传递的数据更新 message data 属性。

具有自定义事件的事件修饰符

虽然像 .prevent.stop 这样的事件修饰符通常用于原生 DOM 事件,但 Vue 也提供了在处理自定义事件时有用的修饰符,尤其是 .once

  • .once:此修饰符确保事件处理程序仅触发一次。
<template><child-component @custom-event.once="handleCustomEvent"></child-component>
</template>

在这种情况下,handleCustomEvent 只会在第一次发出 custom-event 时调用。

示例:实现 counter 组件

让我们创建一个可重用的 counter 组件,当计数递增或递减时,它会发出自定义事件。

// Counter.vue
<template><div><button @click="decrement">-</button><span>{{ count }}</span><button @click="increment">+</button></div>
</template><script>
export default {data() {return {count: 0};},methods: {increment() {this.count++;this.$emit('increment', this.count);},decrement() {this.count--;this.$emit('decrement', this.count);}}
};
</script>
// ParentComponent.vue
<template><div><Counter @increment="onIncrement" @decrement="onDecrement" /><p>Current Count: {{ currentCount }}</p></div>
</template><script>
import Counter from './Counter.vue';export default {components: {Counter},data() {return {currentCount: 0};},methods: {onIncrement(count) {this.currentCount = count;},onDecrement(count) {this.currentCount = count;}}
};
</script>

在此示例中,每当单击相应的按钮时,Counter 组件都会发出 incrementdecrement 事件。父组件侦听这些事件并更新其自己的 currentCount 数据属性。

Scoped Slots:灵活的组件渲染

作用域插槽为父组件提供了一种将模板注入子组件的方法,同时仍然可以访问子组件中的数据。这允许高度可定制和可重用的组件。

了解作用域插槽

作用域插槽是一种特殊类型的插槽,它允许父组件从子组件的作用域访问数据。这是通过将数据作为插槽的属性传递来实现的。

在子组件中定义作用域插槽

要定义作用域插槽,请使用 <slot> 元素并将数据作为属性绑定到它。

// ListComponent.vue
<template><ul><li v-for="item in items" :key="item.id"><slot name="item" :item="item">{{ item.name }}</slot></li></ul>
</template><script>
export default {props: {items: {type: Array,required: true}}
};
</script>

在此示例中,ListComponent 呈现项目列表。名称为 “item” 的 <slot> 元素是有作用域的槽。 物品数据作为插槽的属性传递。如果没有为插槽提供内容,则将呈现回退内容 {{ item.name }}

在父组件中使用 Scoped 插槽

要使用作用域插槽,请在子组件标签中的 <template> 元素上使用 v-slot 指令(或其简写 #)。v-slot 的值是插槽的名称,该值也可以解构以访问插槽的属性。

// ParentComponent.vue
<template><div><ListComponent :items="items"><template #item="{ item }"><strong>{{ item.name }}</strong> - {{ item.description }}</template></ListComponent></div>
</template><script>
import ListComponent from './ListComponent.vue';export default {components: {ListComponent},data() {return {items: [{ id: 1, name: 'Apple', description: 'A red fruit' },{ id: 2, name: 'Banana', description: 'A yellow fruit' }]};}
};
</script>

在此示例中,父组件使用 ListComponent 并为 “item” 插槽提供自定义模板。v-slot=“{ item }” 语法将 item 属性从插槽的范围内解构出来,允许父组件访问项目数据并将其渲染为 <strong>{{ item.name }}</strong> - {{ item.description }} .

命名作用域插槽

组件可以有多个作用域插槽,每个插槽都有一个唯一的名称。这允许在自定义组件的渲染时具有更大的灵活性。

// LayoutComponent.vue
<template><div class="layout"><header><slot name="header"></slot></header><main><slot></slot> <!-- Default slot --></main><footer><slot name="footer"></slot></footer></div>
</template>
// ParentComponent.vue
<template><LayoutComponent><template #header><h1>My Page Title</h1></template><template #default><p>Main content of the page.</p></template><template #footer><p>&copy; 2023</p></template></LayoutComponent>
</template><script>
import LayoutComponent from './LayoutComponent.vue';export default {components: {LayoutComponent}
};
</script>

在这个例子中,LayoutComponent 有三个插槽:“header”、“default”(未命名)和 “footer”。父组件为每个插槽提供自定义内容,允许它定义布局的结构和内容。

示例:创建具有 Scoped 插槽的 Table 组件

让我们创建一个可重用的 table 组件,该组件使用作用域插槽来允许父组件自定义每个单元格的渲染。

// TableComponent.vue
<template><table><thead><tr><th v-for="header in headers" :key="header">{{ header }}</th></tr></thead><tbody><tr v-for="row in data" :key="row.id"><td v-for="header in headers" :key="header"><slot :name="header" :row="row">{{ row[header] }}</slot></td></tr></tbody></table>
</template><script>
export default {props: {headers: {type: Array,required: true},data: {type: Array,required: true}}
};
</script>
// ParentComponent.vue
<template><div><TableComponent :headers="headers" :data="data"><template #name="{ row }"><strong>{{ row.name }}</strong></template><template #age="{ row }"><span v-if="row.age >= 18">Adult</span><span v-else>Minor</span></template></TableComponent></div>
</template><script>
import TableComponent from './TableComponent.vue';export default {components: {TableComponent},data() {return {headers: ['name', 'age', 'city'],data: [{ id: 1, name: 'John Doe', age: 25, city: 'New York' },{ id: 2, name: 'Jane Doe', age: 17, city: 'Los Angeles' }]};}
};
</script>

在此示例中,TableComponent 根据提供的 headersdata props 呈现一个表。对于每个 cell,它使用与 header name 对应的命名范围槽。父组件为 “name” 和 “age” 列提供自定义模板,允许它自定义这些单元格的呈现。

相关文章:

vue-09(使用自定义事件和作用域插槽构建可重用组件)

实践练习&#xff1a;使用自定义事件和作用域插槽构建可重用组件 构建可重用的组件是高效 Vue.js 开发的基石。本课重点介绍如何通过自定义事件和范围插槽来增强组件的可重用性&#xff0c;从而实现更灵活和动态的组件交互。我们将探索如何定义和发出自定义事件&#xff0c;使…...

简单三步FastAdmin 开源框架的安装

简单三步FastAdmin 开源框架的安装 第一步&#xff1a;新建站点1&#xff0c;在宝塔面板中&#xff0c;创建一个新的站点&#xff0c;并填写项目域名。 第二步&#xff1a;上传框架1&#xff0c;框架下载2&#xff0c;上传解压缩 第三步&#xff1a;配置并安装1&#xff0c;进入…...

RISC-V 开发板 MUSE Pi Pro 搭建 Spacengine AI模型部署环境

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro 搭建 Spacengine AI模型部署环境 Spacengine 是由 进迭时空 研发的一套 AI 算法模型部署工具&#xff0c;可以方便的帮助用户部署自己的模型在端侧&#xff0c; 环境部署的方式&#xff0c;官方提供了两种方式&#xff1a; do…...

C++面试5——对象存储区域详解

C++对象存储区域详解 核心观点:内存是程序员的战场,存储区域决定对象的生杀大权!栈对象自动赴死,堆对象生死由你,全局对象永生不死,常量区对象只读不灭。 一、四大地域生死簿 栈区(Stack) • 特点:自动分配释放,速度极快(类似高铁进出站) • 生存期:函数大括号{}就…...

【Unity】AudioSource超过MaxDistance还是能听见

unity版本&#xff1a;2022.3.51f1c1 将SpatialBlend拉到1即可 或者这里改到0 Hearing audio outside max distance - #11 by wderstine - Questions & Answers - Unity Discussions...

基于 51 单片机的智能饮水机控制系统设计与实现

一、引言 随着物联网技术的发展,传统家电的智能化升级成为趋势。本文提出一种基于 51 单片机的智能饮水机设计方案,实现水温精准控制、水位监测、人机交互等功能,具有成本低、稳定性高的特点,适用于家庭和小型办公场景。 二、硬件设计 2.1 核心芯片选型 单片机:选用STC…...

Qt 读取和写入 INI 格式的配置文件

Qt 读取和写入 INI 格式的配置文件 前言&#xff1a;INI 配置文件在 Qt 开发中的重要性基础夯实&#xff1a;INI 文件结构与 QSettings 核心概念1. INI 文件的基本结构2. QSettings 类概述3. 初始化 QSettings 对象4. 基本读写操作5. 高级操作技巧5.1 处理数组和列表5.2 检查键…...

互联网大厂Java求职面试:AI与云原生架构实战解析

互联网大厂Java求职面试&#xff1a;AI与云原生架构实战解析 面试背景设定 场景&#xff1a;某互联网头部企业技术总监办公室&#xff0c;窗外是城市夜景&#xff0c;室内灯光柔和。面试官是一位经验丰富的技术总监&#xff0c;面前摆着一杯黑咖啡和候选人的简历。 候选人&a…...

Spring:从青铜到王者,你的Java修炼手册

一、Spring家族宇宙&#xff1a;原来你是这样的框架&#xff08;青铜段位&#xff09; 1.1 Spring的"前世今生"&#xff1a;从泡面到满汉全席 ​​2002年的泡面哲学​​&#xff1a;Rod Johnson在厨房煮泡面时突然顿悟&#xff1a;"Java开发为什么不能像泡面一…...

React和原生事件的区别

一、核心差异对比表 维度原生事件React 事件绑定语法HTML 属性&#xff08;onclick&#xff09;或 DOM API&#xff08;addEventListener&#xff09;JSX 中使用驼峰式属性&#xff08;onClick&#xff09;绑定位置直接绑定到具体 DOM 元素统一委托到根节点&#xff08;React …...

Qt creator 设计页面控件认识与了解

记录一下 Qt 中的认识与了解&#xff1a; 在 Qt 中&#xff0c;这些功能属于 Qt Designer 的组件过滤系统&#xff0c;旨在帮助开发者在对象浏览器中快速定位和使用不同类型的控件和组件。以下是每个功能的详细讲解&#xff1a; ‌Layouts&#xff08;布局&#xff09;‌&…...

命象架构法 02|你的系统有“用神”吗?

命理中说:“八字无用神,是虚命。” 系统架构中说:“模块无主线,是垃圾桶。” 你设计了无数类,却不知道哪个是核心。 那么你的系统,很可能是没有“用神”的。 01|什么是“用神”?不是你以为的“最好” 命理中,“用神”不是“最强的”,而是对命主最有帮助的。 比如一…...

NVIDIA Mellanox BlueField-2 DPU(Data Processing Unit)智能网卡的调试和使用

专有名词 OOB&#xff1a; BMC&#xff1a; BFB&#xff1a; EMMC&#xff1a; 关键词解释eMMCEmbedded Multi-Media Card——把 NAND 闪存颗粒与控制器封装在一起的板载存储件&#xff0c;类似手机里的“内置储存” .deb&#xff1a;文件是​​Debian软件包格式​​的专…...

Tomcat- AJP协议文件读取/命令执行漏洞(幽灵猫复现)详细步骤

一、漏洞描述 Apache Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器.默认情况下,Apache Tomcat会开启AJP连接器,方便与其他Web服务器通过AJP协议进行交互.但Apache Tomcat在AJP协议的实现上存在漏洞,导致攻击者可以通过发送恶意的AJP请求,可以读取或者包含Web应…...

B1、进度汇报(— 25/05/31)

本文档汇总了各成员在 2025 年 5 月 11 日 ~ 5 月 31 日完成的工作。我们遇到了进度问题&#xff08;收工后需反思&#xff09;&#xff1a; 本学期第十四周&#xff08;05/19 ~ 05/25&#xff09;有相当多课程需要提交实验结果或上台展示。本学期第十六周&#xff08;06/02 ~…...

工作流引擎-11-开源 BPM 项目 jbpm

工作流引擎系列 工作流引擎-00-流程引擎概览 工作流引擎-01-Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎&#xff0c;支持现实世界的流程自动化需求 工作流引擎-02-BPM OA ERP 区别和联系 工作流引擎-03-聊一聊流程引擎 工作流引擎-04-流程引擎 activiti 优…...

【Prompt Engineering】摸索出的一些小套路

prompt 优化方法 &#x1f539; 1. 通用结构模板 模块化的Prompt&#xff1a;Prompt 划分成边界清晰的模块&#xff0c;不同模块间都应有明确的分隔符 以下是通用 Prompt 的推荐结构&#xff1a; [角色设定] [任务描述] [输出格式要求] [补充上下文]角色设定&#xff1a;…...

CSS强制div单行显示不换行

在CSS中&#xff0c;要让<div>的内容强制单行显示且不换行&#xff0c;可通过以下属性组合实现&#xff1a; 核心解决方案&#xff1a; css 复制 下载 div {white-space: nowrap; /* 禁止文本换行 */overflow: hidden; /* 隐藏溢出内容 */text-overflow: e…...

js的时间循环的讲解

JavaScript 事件循环(Event Loop)是其运行时的核心机制,负责处理异步操作,确保单线程的 JavaScript 能够高效地处理并发任务。下面从多个角度详细解析事件循环机制: 1. 核心概念 (1)执行栈(Call Stack) 定义:JavaScript 是单线程的,所有同步任务都在执行栈中依次执…...

Flutter实现不规则瀑布流布局拖拽重排序

因为业务&#xff0c;所以需要用flutter去实现一种不规则图形的瀑布流&#xff0c;但是同时需要支持拖拽并重新排序。效果类似如下。 查询过现有的插件&#xff0c;要么是仅支持同样大小的组件进行排序&#xff0c;要么就是动画效果不是很满意&#xff0c;有点死板&#xff0c;…...

【第4章 图像与视频】4.1 图像的绘制

文章目录 前言在 Canvas 之中绘制图像drawImage() 方法的用法 前言 drawImage() 方法可以将一幅图像的整体或某个部分绘制到 canvas 内的任何位置上&#xff0c;并且允许开发者在绘制过程中对图像进行缩放。也可以将图像绘制在离屏 canvas 中&#xff0c;这样的话就可以对图像…...

苹果应用开发详细教程(2025最新版)

苹果应用开发详细教程(2025最新版) 第一阶段:开发环境搭建 硬件准备 Mac电脑(macOS Monterey 12或更高版本)iPhone/iPad(真机调试建议iOS 16+)软件安装 # 通过App Store安装Xcode xcode-select --installXcode 15+(包含Swift 5.9编译器)安装CocoaPods(依赖管理工具)…...

G25-05-31Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2025-05-31统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10TypeScript项目1Pake: 利用 Rust 轻松构建轻量级多端桌面应用 创建周期:491 天开发语言:Rust协议类型:MIT LicenseStar数量:2095…...

2025年主流编程语言全面分析与学习指南

文章目录 2025年主流编程语言全面分析与学习指南目录简介Python优势局限性学习路径适合人群 JavaScript优势局限性学习路径适合人群 Java优势局限性学习路径适合人群 C优势局限性学习路径适合人群 Rust优势局限性学习路径适合人群 Swift优势局限性学习路径适合人群 Go优势局限性…...

window安装nginx

步骤1&#xff1a;下载Nginx for Windows​ 访问Nginx官网下载页面&#xff1a;https://nginx.org/en/download.html 在​​Stable version​​&#xff08;稳定版&#xff09;下找到Windows版本&#xff0c;点击下载.zip文件&#xff08;如 nginx-1.28.0.zip&#xff09; 步…...

ArcGIS Pro裁剪影像

方法1&#xff1a; 工具箱中&#xff0c;数据管理工具-栅格-栅格处理-裁剪栅格 注意&#xff1a;勾选上使用输入要素裁剪几何 方法2&#xff1a; 按掩膜提取工具裁剪栅格&#xff1a;在工具箱中&#xff0c;Spatial Analyst工具-提取分析-按掩膜提取...

[智能算法]蚁群算法原理与TSP问题示例

目录 ​编辑 一、生物行为启发的智能优化算法 1.1 自然界的群体智能现象 1.2 人工蚁群算法核心思想 二、算法在组合优化中的应用演进 2.1 经典TSP问题建模 2.2 算法流程优化 三、TSP问题实战:Python实现与可视化 3.1 算法核心类设计 3.2 参数敏感性实验 3.3 可视化…...

Vue-4-前端框架Vue基础入门之Vue的常用操作

文章目录 1 VUE1.1 文件结构1.2 定义和显示变量1.2.1 ref函数1.2.2 reactive函数1.3 定义方法1.3.1 方式一1.3.2 方式二1.3.3 方式三1.4 循环遍历1.5 watch1.5.1 监听ref1.5.2 监听reactive1.6 生命周期函数1.7 配置文件2 问题及解决2.1 lack permissions2.2 npm run dev! Miss…...

ubuntu国内镜像源手动配置

备份当前源列表 打开终端&#xff0c;执行以下命令备份当前的源列表&#xff1a; sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup 编辑源列表文件 使用文本编辑器编辑/etc/apt/sources.list文件&#xff0c;例如使用nano&#xff1a; sudo vim /etc/apt/sou…...

21-CS61B-lab6:java文件操作以及持久化一见

文件操作 这里的文件操作主要通过File类&#xff0c;Serializable的派生类等实现 拥有路径path(相对路径/绝对路径)&#xff0c;创建File对象 File newFile new File(path); 获得当前工作目录File File CWD new File(System.getProperty("user.dir")); 通过S…...