Vue.js事件处理

本章将深入讲解Vue.js中的事件处理机制,包括事件监听、事件修饰符、按键修饰符等。

什么是事件处理?

在Vue.js中,可以使用v-on指令监听DOM事件,并在触发时执行一些JavaScript代码。

基本语法

<!-- 内联事件处理 -->
<button v-on:click="counter += 1">增加 1</button>

<!-- 使用方法事件处理 -->
<button v-on:click="greet">问候</button>

<!-- 简写形式 -->
<button @click="greet">问候</button>
                            

内联事件处理器

内联事件处理器适用于简单的逻辑:


<div id="inline-handler-example">
    <button @click="count++">
        点击次数: {{ count }}
    </button>

    <button @click="sayHello('Vue.js')">
        打招呼
    </button>
</div>

<script>
new Vue({
    el: '#inline-handler-example',
    data: {
        count: 0
    },
    methods: {
        sayHello(name) {
            alert('你好, ' + name + '!');
        }
    }
});
</script>
                        

方法事件处理器

对于复杂的事件处理逻辑,推荐使用方法事件处理器:


<div id="method-handler-example">
    <button @click="handleClick">
        点击我
    </button>

    <button @click="handleEvent($event, '额外参数')">
        带参数的事件
    </button>
</div>

<script>
new Vue({
    el: '#method-handler-example',
    methods: {
        handleClick() {
            // 访问原生DOM事件
            console.log('按钮被点击了!');
        },
        handleEvent(event, extraParam) {
            // event是原生DOM事件
            console.log('事件类型:', event.type);
            console.log('额外参数:', extraParam);
            console.log('点击的元素:', event.target.tagName);
        }
    }
});
</script>
                        
注意:在方法中可以通过$event访问原始的DOM事件对象。

事件修饰符

Vue.js提供了事件修饰符来处理DOM事件的细节:

修饰符 描述 示例
.stop 阻止事件冒泡 @click.stop="doThis"
.prevent 阻止默认行为 @submit.prevent="onSubmit"
.capture 使用事件捕获模式 @click.capture="doThis"
.self 仅当事件在元素本身触发时调用 @click.self="doThat"
.once 事件只触发一次 @click.once="doThis"
.passive 用于移动端滚动性能优化 @scroll.passive="onScroll"

<!-- 阻止单击事件继续传播 -->
<div @click="handleOuterClick">
    <button @click.stop="handleInnerClick">内部按钮</button>
</div>

<!-- 提交事件不再重载页面 -->
<form @submit.prevent="handleSubmit">
    <input type="text" v-model="username">
    <button type="submit">提交</button>
</form>

<!-- 修饰符可以串联 -->
<a @click.stop.prevent="doThat">链接</a>

<!-- 只有修饰符 -->
<form @submit.prevent>
    <!-- 表单提交不会刷新页面 -->
</form>
                        

按键修饰符

Vue.js允许为v-on在监听键盘事件时添加按键修饰符:


<!-- 按键码 -->
<input @keyup.13="submit">

<!-- 按键别名 -->
<input @keyup.enter="submit">
<input @keyup.tab="nextField">
<input @keyup.delete="deleteItem">
<input @keyup.esc="cancel">
<input @keyup.space="playPause">

<!-- 方向键 -->
<input @keyup.up="moveUp">
<input @keyup.down="moveDown">
<input @keyup.left="moveLeft">
<input @keyup.right="moveRight">

<!-- 组合示例 -->
<input v-model="message"
       @keyup.enter="submitForm"
       @keyup.esc="clearForm">
                        
小贴士:Vue.js为最常用的按键提供了别名:.enter.tab.delete.esc.space.up.down.left.right

系统修饰键

系统修饰键可以实现组合按键的功能:


<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">按住Ctrl点击</div>

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear">

<!-- Shift + Click -->
<button @click.shift="handleShiftClick">按住Shift点击</button>

<!-- Ctrl + S -->
<div @keydown.ctrl.s="saveContent">
    按Ctrl+S保存
</div>

<!-- .exact修饰符 -->
<button @click.exact="onClick">只有点击,没有其他键</button>
<button @click.ctrl.exact="onCtrlClick">只有Ctrl+点击</button>
                        

鼠标按钮修饰符

限制特定的鼠标按钮触发事件:


<!-- 左键点击 -->
<button @click.left="leftClick">左键</button>

<!-- 右键点击 -->
<button @click.right="rightClick">右键</button>
<div @contextmenu.prevent="showContextMenu">
    右键点击显示菜单
</div>

<!-- 中键点击 -->
<button @click.middle="middleClick">中键</button>

<!-- 阻止右键菜单默认行为 -->
<div @contextmenu.prevent>
    右键不会显示浏览器菜单
</div>
                        

完整示例

下面是一个综合的事件处理示例:


<div id="event-example">
    <!-- 计数器 -->
    <div class="mb-3">
        <button @click="increment" class="btn btn-primary me-2">
            增加 (+)
        </button>
        <button @click="decrement" class="btn btn-secondary me-2">
            减少 (-)
        </button>
        <span class="badge bg-info">计数: {{ count }}</span>
    </div>

    <!-- 表单处理 -->
    <form @submit.prevent="handleSubmit" class="mb-3">
        <div class="mb-2">
            <input type="text"
                   v-model="username"
                   @keyup.enter="submitForm"
                   placeholder="按Enter键提交"
                   class="form-control">
        </div>
        <button type="submit" class="btn btn-success me-2">
            提交表单
        </button>
        <button type="button" @click="resetForm" class="btn btn-warning">
            重置
        </button>
    </form>

    <!-- 鼠标事件 -->
    <div @mouseenter="highlight = true"
         @mouseleave="highlight = false"
         :class="{ 'bg-warning': highlight }"
         class="p-3 border rounded mb-3">
        鼠标移入移出效果
    </div>

    <!-- 事件详情显示 -->
    <div class="alert alert-secondary">
        <h6>最近事件:</h6>
        <ul>
            <li v-for="event in recentEvents">{{ event }}</li>
        </ul>
    </div>
</div>

<script>
new Vue({
    el: '#event-example',
    data: {
        count: 0,
        username: '',
        highlight: false,
        recentEvents: []
    },
    methods: {
        increment() {
            this.count++;
            this.logEvent('增加计数');
        },
        decrement() {
            this.count--;
            this.logEvent('减少计数');
        },
        handleSubmit() {
            if (this.username.trim()) {
                alert('提交用户名: ' + this.username);
                this.logEvent('提交表单: ' + this.username);
            }
        },
        submitForm() {
            this.handleSubmit();
        },
        resetForm() {
            this.username = '';
            this.logEvent('重置表单');
        },
        logEvent(eventName) {
            const time = new Date().toLocaleTimeString();
            this.recentEvents.unshift(`[${time}] ${eventName}`);
            // 只保留最近的5个事件
            if (this.recentEvents.length > 5) {
                this.recentEvents.pop();
            }
        }
    }
});
</script>
                        
最佳实践:
  • 对于复杂逻辑,使用方法事件处理器而非内联处理器
  • 合理使用事件修饰符简化代码
  • 考虑使用.prevent防止表单默认提交行为
  • 在移动端使用.passive修饰符优化滚动性能
  • 使用$event参数访问原始事件对象