事件绑定
学习:v-on以及简写形式,methods应用
我们可以使用 v-on
指令 (简写为 @
) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:click="methodName"
或 @click="handler"
。
事件处理器的值可以是:
- 内联事件处理器:事件被触发时执行的内联 JavaScript 语句 (与
onclick
类似)。 - 方法事件处理器:一个指向组件上定义的方法的属性名或是路径。
·内联事件处理器·通常用于简单场景,例如:
<button @click="count++">加 1</button> <p>Count is: {{ count }}</p>
随着事件处理器的逻辑变得愈发复杂,内联代码方式变得不够灵活。因此 v-on
也可以接受一个方法名或对某个方法的调用。
方法事件处理器
<button @click="greet">问候</button> data () { return { name: 'Vue.js' } }, methods: { greet(event) { // 方法中的 `this` 指向当前活跃的组件实例 alert(`Hello ${this.name}!`) // `event` 是 DOM 原生事件 if (event) { alert(event.target.tagName) } } }
除了直接绑定方法名,你还可以在内联事件处理器中调用方法。这允许我们向方法传入自定义参数以代替原生事件:
methods: { say(message) { alert(message) } }
<button @click="say('hello')">说 hello</button> <button @click="say('bye')">说 bye</button>
内联事件处理器中访问原生 DOM 事件。你可以向该处理器方法传入一个特殊的 $event
变量,或者使用内联箭头函数:
<!-- 使用特殊的 $event 变量 --> <button @click="warn('表单不能提交.', $event)">提交</button> <!-- 使用内联箭头函数 --> <button @click="(event) => warn('表单不能提交.', event)">提交</button>
methods: { warn(message, event) { // 这里可以访问 DOM 原生事件 if (event) { event.preventDefault() } alert(message) } }
在处理事件时调用 event.preventDefault()
或 event.stopPropagation()
是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。
为解决这一问题,Vue 为 v-on
提供了事件修饰符。
<!-- 单击事件将停止传递 --> <a @click.stop="doThis"></a> <!-- 提交事件将不再重新加载页面 --> <form @submit.prevent="onSubmit"></form> <!-- 修饰语可以使用链式书写 --> <a @click.stop.prevent="doThat"></a> <!-- 也可以只有修饰符 --> <form @submit.prevent></form> <!-- 仅当 event.target 是元素本身时才会触发事件处理器 --> <!-- 例如:事件处理器不来自子元素 --> <div @click.self="doThat">...</div> <!-- 添加事件监听器时,使用 `capture` 捕获模式 --> <!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 --> <div @click.capture="doThis">...</div> <!-- 点击事件最多被触发一次 --> <a @click.once="doThis"></a> <!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 --> <!-- 以防其中包含 `event.preventDefault()` --> <div @scroll.passive="onScroll">...</div>
<!-- 事件修饰符 --> <!-- 阻止冒泡-原生 --> <div class="parent" @click="clickParent1"> <div class="child" @click="clickChild1"></div> </div> <!-- 阻止冒泡-事件修饰符 --> <div class="parent" @click="clickParent2"> <div class="child" @click.stop="clickChild2"></div> </div>
methods: { clickParent1 (event) { console.log('parent1') }, clickChild1 (event) { event.stopPropagation() console.log('child1') }, clickParent2 (event) { console.log('parent2') }, clickChild2 (event) { console.log('child2') }, }
.parent { width: 200px; height: 200px; background: #f66; display: flex; justify-content: center; align-items: center; margin-top: 10px; } .child { width: 100px; height: 100px; border: 1px solid #ccc; }
在处理事件时调用 event.preventDefault()
或 event.stopPropagation()
是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。
为解决这一问题,Vue 为 v-on
提供了事件修饰符。
<!-- 单击事件将停止传递 --> <a @click.stop="doThis"></a> <!-- 提交事件将不再重新加载页面 --> <form @submit.prevent="onSubmit"></form> <!-- 修饰语可以使用链式书写 --> <a @click.stop.prevent="doThat"></a> <!-- 也可以只有修饰符 --> <form @submit.prevent></form> <!-- 仅当 event.target 是元素本身时才会触发事件处理器 --> <!-- 例如:事件处理器不来自子元素 --> <div @click.self="doThat">...</div> <!-- 添加事件监听器时,使用 `capture` 捕获模式 --> <!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 --> <div @click.capture="doThis">...</div> <!-- 点击事件最多被触发一次 --> <a @click.once="doThis"></a> <!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 --> <!-- 以防其中包含 `event.preventDefault()` --> <div @scroll.passive="onScroll">...</div>
<!-- 事件修饰符 --> <!-- 阻止冒泡-原生 --> <div class="parent" @click="clickParent1"> <div class="child" @click="clickChild1"></div> </div> <!-- 阻止冒泡-事件修饰符 --> <div class="parent" @click="clickParent2"> <div class="child" @click.stop="clickChild2"></div> </div>
methods: { clickParent1 (event) { console.log('parent1') }, clickChild1 (event) { event.stopPropagation() console.log('child1') }, clickParent2 (event) { console.log('parent2') }, clickChild2 (event) { console.log('child2') }, }
.parent { width: 200px; height: 200px; background: #f66; display: flex; justify-content: center; align-items: center; margin-top: 10px; } .child { width: 100px; height: 100px; border: 1px solid #ccc; }
在监听键盘事件时,我们经常需要检查特定的按键。Vue 允许在 v-on
或 @
监听按键事件时添加按键修饰符
。
<!-- 按键修饰符 --> <!-- 原生 --> <input type="text" @keyup="print1"> <!-- vue --> <input type="text" @keyup.enter="print2">
methods: { print1 (event) { if (event.keyCode === 13) { console.log('打印1') } }, print2 () { console.log('打印2') } }
.enter .tab .delete (捕获“Delete”和“Backspace”两个按键) .esc .space .up .down .left .right
你可以使用以下系统按键修饰符
来触发鼠标或键盘事件监听器,只有当按键被按下时才会触发
.ctrl .alt .shift .meta
<!-- Alt + Enter --> <input @keyup.alt.enter="clear" /> <!-- Ctrl + 点击 --> <div @click.ctrl="doSomething">Do something</div>
完整案例: 02_tempalte/04_event.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>事件绑定</title> <style> .container { width: 200px; height: 200px; background-color: #f66; } .box { width: 100px; height: 100px; background-color: #0f0; } </style> </head> <body> <div id="app"> <!-- 内联事件处理器: 使用表达式,不要使用js中的方法 类似于alert以及console,可以在方法事件处理器中使用 --> <button @click="count+=2">加2</button> <button @click="count++">加1</button> <!-- alert is not a function --> <button @click="alert(1)">弹出提示</button> <!-- Cannot read properties of undefined --> <button @click="console.log(1)">打印提示</button> {{ count }} <!-- 方法事件处理器 --> <div> <button @click="add">加10</button> <button @click="addFn(5, $event)">加参数</button> {{ num }} </div> <!-- 事件修饰符 --> <div class="container" @click="print('container')"> <div class="box" @click="print('box', $event)"></div> </div> <div class="container" @click="printFn('container')"> <div class="box" @click.stop="printFn('box')"></div> </div> <div class="container" @click.self="printFn('container')"> <div class="box" @click="printFn('box')"></div> </div> <!-- .stop .prvent .self --> <!-- 按键修饰符 - 输入表单 --> <input type="text" @keyup="output"> <input type="text" @keyup.enter="outputFn"> <!-- vue2可以使用keyCode值作为修饰符 --> <input type="text" @keyup.13="outputFn"> <!-- 系统修饰按键 --> <div> <input type="text" @keyup.alt.enter="systemOutput"> </div> </div> </body> <script src="../lib/vue.global.js"></script> <script> Vue.createApp({ data () { return { count: 10, num: 100 } }, methods: { add (event) { console.log(event) this.num += 10 }, addFn (params, event) { console.log(event) this.num += params }, print (params, event) { if (event) { event.stopPropagation() } console.log(params) }, printFn (params) { console.log(params) }, output (event) { if (event.keyCode === 13) { console.log('11111') } }, outputFn () { console.log('11111') }, systemOutput () { console.log('2222') } } }).mount('#app') </script> </html>