Vue-事件处理

事件处理

监听事件

可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

实例:

<div id="box">
  <button v-on:click="counter++">Add 1</button>
  <p>The button above has been clicked {{ counter }} times.</p>
</div>
var example1 = new Vue({
    el: '#box',
    data: {
        counter: 0
    }
})

事件处理方法

然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。

实例:

<div id='box'>
    <button @click='fn'>
        click
    </button>
</div>
let vm = new Vue({
    el:'#box',
    data:{
        name:'retr0'
    }
    method:{
    //当@click='fn'不加括号时,可以直接使用形参eve
    //eve是原生 DOM 事件
    //当@click='fn($event)'加括号时,需要传入实参$event
        fn(eve){
            alert(`hello ${this.name}`);
            if(eve){
                alert(eve.target.tagName);
            }
        }
    }
})

内联处理器中的方法

除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:

<div id="example-3">
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button>
</div>
new Vue({
    el: '#example-3',
    methods: {
        say: function (message) {
            alert(message)
        }
    }
})

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:

<button v-on:click="warn('Form cannot be submitted yet.', $event)">
    Submit
</button>
// ...
methods: {
    warn: function (message, event) {
        // 现在我们可以访问原生事件对象
        if (event) {
            event.preventDefault()
        }
        alert(message)
    }
}

事件修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive

.stop

<!-- 阻止事件冒泡 -->
<a v-on:click.stop="doThis"></a>
<!-- 阻止事件冒泡,没有表达式 -->
<a v-on:click.stop></a>

.prevent

<!-- 阻止浏览器默认行为 -->
<div :click.prevent='fn()'></div>
<!-- 阻止默认行为,没有表达式 -->
<div :click.prevent></div>

.self

<!-- 只当事件是从侦听器绑定的元素本身触发时才触发回调 -->
<ul @click.self='fn2()'>
    <li v-for='data in datalist' @click='fn()'>{{data}}</li>
</ul>

.once

<!-- 只触发一次回调 -->
<div @click.once='fn'></div>

如何不用once做到解绑事件:

<!-- 通过状态isActive进行短路 -->
<!-- 需要注意,这里的函数表达式必须加() -->
<div @click='isActive && fn()'>解绑测试</div>

.passive

每次事件产生,浏览器都会去查询一下是否有preventDefault阻止该次事件的默认动作。我们加上passive就是为了告诉浏览器,不用查询了,我们没用 preventDefault阻止默认动作。这里一般用在滚动监听,@scroll,@touchmove 。因为滚动监听过程中,移动每个像素都会产生一次事件,每次都使用内核线程查询prevent会使滑动卡顿。我们通过passive将内核线程查询跳过,可以大大提升滑动的流畅度

<!-- 以 { passive: true } 模式添加侦听器 -->
<div @click.passive='fn'></div>

按键修饰符

<!-- 只有在按下回车键的时才会触发该事件 -->
<input @keyup.enter='fn()'>
<!-- 支持连缀 -->
<input @keyup.enter.ctrl='fn()'>
<!-- 支持keyCode -->
<input @keyup.13='fn()'>

其实通过以下方法完成的:

<div id='box'>
    <input @keyup='fn1($event)'>
</div>
new Vue({
    el:'#box',
    methods:{
        fn1(eve){
            if(eve.keyCode == 13){
                ......
            }
        }
    }
})