Vue3专题 - 事件处理

大家好,我是Java1234_小锋老师,最近更新 《一天学会 Vue3 + Vite + element-plus UI框架 视频教程》专辑,感谢大家支持。

本课程主要介绍和讲解 Vue3框架,Vite构建工具,以及element-plus UI框架。Vue3核心知识介绍,Vite构建工具使用,以及element-plus UI框架的基础组件,配置组件,Form 表单组件,Data 数据展示组件,Navigation导航组件,Feedback反馈组件,Container布局组件介绍和使用。

视频教程+课件+源码打包下载 :

链接:https://pan.baidu.com/s/1o-zRfndo1HHrS_uFroOiCw?pwd=1234

提取码:1234

具体位置 - > 第四阶段富客户端技术里面

Vue3专题 - 事件处理

事件处理用来监听用户操作 (点击、输入、键盘等),并执行对应逻辑。Vue3 用 v-on 指令,模板里通常写成更短的 @

适合:按钮点击、表单提交、键盘回车搜索、阻止默认行为等场景。


1. 为什么需要事件处理?

页面交互几乎都建立在「用户做了某件事 → 程序做出反应」。原生写法要自己 addEventListener,还要自己管解绑。Vue 里把事件和响应式数据绑在一起,写法更集中:

vue 复制代码
<!-- 推荐:声明式绑定 -->
<button @click="count++">点我</button>

<!-- 等价完整写法 -->
<button v-on:click="count++">点我</button>

日常开发优先用 @事件名


2. 基本用法

2.1 内联处理

简单逻辑可以直接写在模板里:

vue 复制代码
<script setup>
/**
 * 内联事件 Demo
 * 点击按钮让计数 +1
 */
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <p>计数:{{ count }}</p>
  <button @click="count++">+1</button>
  <button @click="count = 0">清零</button>
</template>

运行截图:

2.2 方法处理

逻辑稍复杂时,写成函数更清晰(也方便复用和加注释):

vue 复制代码
<script setup>
/**
 * 方法事件 Demo
 * 把逻辑放进函数里
 */
import { ref } from 'vue'

const count = ref(0)

/** 计数加一 */
function add() {
  count.value++
}

/** 重置为 0 */
function reset() {
  count.value = 0
}
</script>

<template>
  <p>计数:{{ count }}</p>
  <button @click="add">+1</button>
  <button @click="reset">清零</button>
</template>

运行截图:

注意:模板里写 @click="add"(传函数引用),不要写成 @click="add()" 除非你确实要立刻执行并传参(见下一节)。


3. 传参与事件对象

3.1 给处理函数传参

需要传自定义参数时,写成方法调用:

vue 复制代码
<script setup>
/**
 * 事件传参 Demo
 */
import { ref } from 'vue'

const msg = ref('')

/** 显示问候语 */
function sayHello(name) {
  msg.value = `你好,${name}`
}
</script>

<template>
  <p>{{ msg }}</p>
  <button @click="sayHello('小明')">问候小明</button>
  <button @click="sayHello('小红')">问候小红</button>
</template>

运行截图:

3.2 同时拿到原生事件对象

内联调用时如果还需要原生 event,用 $event

vue 复制代码
<script setup>
/**
 * $event Demo
 * 自定义参数 + 原生事件对象一起用
 */
import { ref } from 'vue'

const info = ref('')

/**
 * 记录点击来源
 * @param {string} label 按钮名称
 * @param {MouseEvent} e 原生事件
 */
function onClick(label, e) {
  info.value = `${label},坐标:(${e.clientX}, ${e.clientY})`
}
</script>

<template>
  <p>{{ info }}</p>
  <button @click="onClick('按钮A', $event)">按钮 A</button>
</template>

运行截图:

如果方法只有一个参数且是事件对象,可以省略 $event

vue 复制代码
<button @click="onClick">点我</button>

对应函数:function onClick(e) { ... }


4. 事件修饰符

修饰符写在事件名后面,用 . 连接,用来处理常见 DOM 细节,少写样板代码。

修饰符 作用
.stop 阻止冒泡(event.stopPropagation()
.prevent 阻止默认行为(event.preventDefault()
.self 只有事件来自元素自身(不是子元素冒泡上来)才触发
.once 只触发一次
.capture 在捕获阶段监听
.passive 对应 addEventListener{ passive: true }

示例:

vue 复制代码
<script setup>
/**
 * 事件修饰符 Demo
 */
import { ref } from 'vue'

const log = ref('')

/** 外层盒子被点击 */
function onOuter() {
  log.value += '外层 → '
}

/** 内层按钮被点击(并阻止冒泡) */
function onInner() {
  log.value += '内层(已 stop) '
}

/** 提交表单(阻止默认刷新) */
function onSubmit() {
  log.value = '表单已提交(页面未刷新)'
}
</script>

<template>
  <p>{{ log }}</p>

  <!-- 点击内层不会触发外层,因为 .stop 阻止了冒泡 -->
  <div @click="onOuter" style="padding: 16px; background: #f0f0f0">
    外层
    <button @click.stop="onInner">内层</button>
  </div>

  <!-- 阻止表单默认提交刷新 -->
  <form @submit.prevent="onSubmit">
    <button type="submit">提交</button>
  </form>

  <!-- 只触发一次 -->
  <button @click.once="log = '只触发了一次'">点我一次</button>
</template>

修饰符可以连写,例如:@click.stop.prevent

运行截图:


5. 按键修饰符

监听键盘时,可以限定具体按键:

写法 说明
@keyup.enter 回车
@keyup.esc Esc
@keyup.space 空格
@keyup.up / .down / .left / .right 方向键
@keyup.ctrl / .alt / .shift / .meta 系统修饰键
vue 复制代码
<script setup>
/**
 * 按键修饰符 Demo
 * 回车触发搜索
 */
import { ref } from 'vue'

const keyword = ref('')
const result = ref('')

/** 模拟搜索 */
function search() {
  result.value = keyword.value
    ? `搜索结果:${keyword.value}`
    : '请输入关键词'
}
</script>

<template>
  <input
    v-model="keyword"
    placeholder="输入后按回车"
    @keyup.enter="search"
  />
  <p>{{ result }}</p>
</template>

也可以组合:@keyup.ctrl.enter="search"(Ctrl + Enter)。

运行截图:


6. 入门综合 Demo

一个迷你待办输入区:支持点击添加、回车添加、清空列表,并演示 .prevent / .stop

vue 复制代码
<script setup>
/**
 * 事件处理综合 Demo
 * - @click / @keyup.enter:添加待办
 * - @submit.prevent:阻止表单刷新
 * - @click.stop:内层操作不冒泡到外层
 */
import { ref } from 'vue'

/** 输入框内容 */
const text = ref('')
/** 待办列表 */
const list = ref([])
/** 底部日志 */
const tip = ref('还没有操作')

/** 添加一条待办 */
function addTodo() {
  const value = text.value.trim()
  if (!value) {
    tip.value = '内容不能为空'
    return
  }
  list.value.push(value)
  text.value = ''
  tip.value = `已添加:${value}`
}

/**
 * 删除某一项
 * @param {number} index 下标
 */
function removeTodo(index) {
  const removed = list.value[index]
  list.value.splice(index, 1)
  tip.value = `已删除:${removed}`
}

/** 清空全部 */
function clearAll() {
  list.value = []
  tip.value = '列表已清空'
}

/** 点击外层容器时的提示 */
function onPanelClick() {
  tip.value = '你点到了面板空白处'
}
</script>

<template>
  <div class="panel" @click="onPanelClick">
    <h3>待办小 Demo</h3>

    <!-- 提交时阻止页面刷新 -->
    <form @submit.prevent="addTodo">
      <input
        v-model="text"
        placeholder="输入待办,回车或点添加"
        @keyup.enter="addTodo"
      />
      <!-- .stop:点按钮不要触发外层 panel 的 click -->
      <button type="submit" @click.stop>添加</button>
      <button type="button" @click.stop="clearAll">清空</button>
    </form>

    <ul>
      <li v-for="(item, index) in list" :key="index">
        {{ item }}
        <button type="button" @click.stop="removeTodo(index)">删除</button>
      </li>
    </ul>

    <p class="tip">{{ tip }}</p>
  </div>
</template>

<style>
.panel {
  padding: 16px;
  background: #f7f8fa;
  border-radius: 8px;
}
.tip {
  color: #666;
  font-size: 14px;
}
button {
  margin-left: 8px;
}
</style>

运行效果预期:

  1. 输入文字后按回车或点「添加」:列表多一条,输入框清空
  2. 点「删除」:只删该项,不会触发面板的「点到空白处」提示(.stop
  3. 点面板空白处:底部 tip 变成「你点到了面板空白处」
  4. 表单提交不会刷新页面(.prevent

运行截图:


7. 快速对照

写法 示例 说明
基本监听 @click="fn" 最常用
内联语句 @click="count++" 适合一行逻辑
传参 @click="fn(id)" 调用方法并传参
原生事件 @click="fn($event)" 需要 event 时
阻止冒泡 @click.stop 等价 stopPropagation
阻止默认 @submit.prevent 等价 preventDefault
只触发一次 @click.once 第二次不再触发
按键 @keyup.enter 限定按键

相关推荐
A24207349301 小时前
React中请求拦截与响应拦截的统一处理方案
前端·javascript·react.js
zyplayer-doc2 小时前
zyplayer-doc企业知识库能做什么:从文档创建、权限管理到AI问答的完整能力
大数据·javascript·数据库·人工智能·pdf·word
烬羽3 小时前
《受控 vs 非受控:你以为用对了 useState,直到你写了那个表单》
javascript·react.js·前端框架
嘟嘟07173 小时前
React 受控组件与非受控组件:表单数据到底归谁管?
前端·javascript·react.js
嘟嘟07173 小时前
React 表单管理进阶:从单字段到带校验的完整登录表单
前端·javascript·react.js
做前端的娜娜子3 小时前
什么是浅拷贝(Shallow Copy)和深拷贝(Deep Copy)?如何手动实现一个深拷贝函数
javascript·面试·掘金·金石计划
xcLeigh3 小时前
编程语言的 AI 友好度排名:Python、JavaScript、TypeScript 谁更适合 AI 辅助
javascript·人工智能·python·ai·typescript·ai编程
宿6743 小时前
vue3-DOM树
前端·javascript·vue.js
谷哥的小弟3 小时前
TypeScript中的any
javascript·typescript