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

Vue.js $emit的介绍和简单使用

前言

在 Vue.js 开发中,组件化是核心思想之一。但组件间的通信是一个重要课题,特别是子组件向父组件传递数据的场景。Vue 提供了多种通信方式,而$emit正是实现子→父通信的关键方法。本文将深入解析$emit的原理、使用场景及最佳实践。

一、$emit 基础:原理与语法

1.1 核心概念

$emit是 Vue 实例的内置方法,用于触发自定义事件。其核心作用是:

  • 创建事件通道:子组件定义并触发事件
  • 传递数据载体:可携带任意类型参数
  • 父组件响应:通过v-on@监听并处理

 1.2 语法结构

// 子组件中触发事件
this.$emit('event-name', payload1, payload2);// 父组件中监听
<ChildComponent @event-name="handleEvent" />

1.3 工作流程图

子组件 (Child)            父组件 (Parent)┌───────────┐            ┌───────────┐│ this.$emit ├───────┐    │ @event    ││('event')   │       │    │ =handler  │└───────────┘       │    └───────────┘▼事件总线│▼┌───────────┐            ┌───────────┐│           │            │ handler() ││  等待触发  │◀──────────┤  处理逻辑  ││           │            │           │└───────────┘            └───────────┘

二、典型应用场景

2.1 表单数据提交

场景:子组件收集表单数据,提交给父组件处理

子组件示例

<template><form @submit.prevent="handleSubmit"><input v-model="username" placeholder="用户名"><button type="submit">提交</button></form>
</template><script>
export default {data() {return { username: '' }},methods: {handleSubmit() {// 触发事件并传递数据this.$emit('form-submit', {username: this.username,timestamp: new Date()});}}
}
</script>

父组件示例

<template><div><FormComponent @form-submit="processForm" /><p v-if="lastSubmit">上次提交: {{ lastSubmit.username }}</p></div>
</template><script>
import FormComponent from './FormComponent.vue';export default {components: { FormComponent },data() { return { lastSubmit: null } },methods: {processForm(data) {// 接收数据并处理this.lastSubmit = data;console.log('接收到表单数据:', data);}}
}
</script>

2.2 状态变更通知

场景:子组件状态变化时通知父组件

子组件示例

<template><div><el-switch v-model="status" @change="onStatusChange" /><span>{{ status ? '开启' : '关闭' }}</span></div>
</template><script>
export default {props: ['initialStatus'],data() {return { status: this.initialStatus }},methods: {onStatusChange(newValue) {// 通知父组件状态变更this.$emit('status-changed', newValue);}}
}
</script>

父组件示例

<template><div><StatusSwitch :initial-status="featureEnabled"@status-changed="updateFeature"/><p>功能状态: {{ featureEnabled ? '启用' : '禁用' }}</p></div>
</template><script>
import StatusSwitch from './StatusSwitch.vue';export default {components: { StatusSwitch },data() { return { featureEnabled: false } },methods: {updateFeature(newStatus) {// 更新状态并可能触发其他操作this.featureEnabled = newStatus;this.$message(`功能已${newStatus ? '启用' : '禁用'}`);}}
}
</script>

2.3 列表项交互

场景:列表组件中的项触发事件

子组件示例

<template><li @click="handleClick">{{ item.name }}<button @click.stop="deleteItem">删除</button></li>
</template><script>
export default {props: ['item'],methods: {handleClick() {this.$emit('item-clicked', this.item.id);},deleteItem() {this.$emit('delete-item', this.item.id);}}
}
</script>

父组件示范:

<template><ul><ListItem v-for="item in list" :key="item.id":item="item"@item-clicked="viewItem"@delete-item="removeItem"/></ul>
</template><script>
import ListItem from './ListItem.vue';export default {components: { ListItem },data() {return {list: [{ id: 1, name: '项目A' },{ id: 2, name: '项目B' }]}},methods: {viewItem(id) {this.$router.push(`/items/${id}`);},removeItem(id) {this.list = this.list.filter(item => item.id !== id);}}
}
</script>

三、进阶技巧与最佳实践

3.1 事件命名规范

  • 推荐风格:使用短横线分隔 (kebab-case)
  • 避免冲突:添加组件前缀 (如 user-form:submit)
  • 语义化:使用动词开头 (如 delete-item 而非 item-delete)

3.2 事件参数优化

// 推荐:传递结构化数据
this.$emit('user-updated', {id: this.userId,name: this.username,action: 'update'
});// 避免:传递零散参数
this.$emit('user-updated', this.userId, this.username, 'update');

3.3 与v-model结合

<template><input :value="value" @input="$emit('input', $event.target.value)">
</template><script>
export default {props: ['value']
}
</script>

3.4 事件验证

props: {// 基础类型检查value: String,// 带验证的事件处理函数onSubmit: {type: Function,required: true,validator: fn => typeof fn === 'function'}
}

四、总结与最佳实践

4.1 适用场景总结

  • 子组件向父组件传递数据
  • 组件状态变更通知
  • 表单数据提交
  • 列表项交互事件

4.2 对比其他通信方式

方式方向复杂度适用场景
$emit子→父简单组件通信
props父→子单向数据流
event bus任意跨级 / 兄弟组件通信
Vuex/Pinia全局大型应用状态管理
provide/inject祖先→后代跨级共享数据

 

http://www.xdnf.cn/news/13471.html

相关文章:

  • 【leetcode-合并两个有序链表】
  • Codeforces Round 1029 (Div. 3)
  • C语言数据结构笔记6:使用宏和指针来设置和操作嵌套在结构体中的联合体数组的特定位
  • OC学习—Block初探(简易版)
  • 【实战指南】前端项目Nginx配置全流程:从打包部署到解决跨域/路由循环问题
  • 在C# 中使用建造者模式
  • 算法题(167):FBI树
  • Oracle日志体系和遇到问题后日志排查路径
  • 行为模式-责任链模式
  • 进行性核上性麻痹健康护理指南:全方位照护之道
  • Pytorch 的编程技巧
  • Java八股文——Spring「Spring 篇」
  • 5.4.2树、森林与二叉树的转换
  • 今日行情明日机会——20250611
  • Android GreenDAO 通过 Key 查询数据库数据慢问题优化
  • 13.自治系统路由计算题
  • Node.js:开启现代服务器端编程的新篇章
  • h5fortran 简介与使用指南
  • 新能源知识库(36)什么是BMU
  • 51LA数据分析遇瓶颈?免费统计工具——悟空统计
  • 大话软工笔记—工程分解
  • GlusterFS分布式文件系统
  • 【Keepalived】Keepalived-2.3.4恢复对RHEL7的支持
  • 第七章: SEO与渲染方式 三
  • (十一)优化算法(Optimization):深度学习训练中的收敛性分析与泛化理论
  • 鹰盾视频加密器Windows播放器AI溯源水印技术方案解析
  • ros2--Sophus
  • “新液冷”破题“智算热”,数字经济低碳化发展新解
  • 【Linux】Linux 操作系统 - 22 , 软硬链接详解 !
  • 104.解决在流式回答功能实现之后上传附件功能失效bug之前端处理