Vue事件处理
在jq中的事件处理,我们都很熟悉了,模式类似于下面这样,通过DOM节点,执行click事件
$("button").click(function () {
$("p").hide();
});
但是在Vue中,我们触发事件,并不是这样的。
首先,绑定方式不一样,在Vue中绑定事件使用的是 v-on: ,当然肯定也是存在简写的,那就是 @ ,例如:绑定按钮事件
<button v-on:click='showInfo'>点击打印信息</button> // 完整写法
<button @click='showInfo'>点击打印信息</button> // 简写
关于绑定方法的位置,Vue 也给我们规定了:需要在配置项内配置 methods 对象,绑定方法保存在其内部
const vm = new Vue({
el: '#root',
data() {
return {
name: 'al'
}
},
methods: {
showInfo() {
console.log('qweqwee')
}
},
})
这个函数参数中,我们并没有传递参数,但是实际上,我们却能在方法内部接收到 event 属性
showInfo() {
console.log(event, 'event')
console.log('qweqwee')
}
如果我们需要传递参数,那只需要在调用时将参数传递进去,且 event 默认会自动传递进去
<button v-on:click='showInfo(66)'>点击打印信息</button>
在methods内部定义的方法上,接收传递的参数,我们发现此时三个打印都已出现在控制台上
const vm = new Vue({
el: '#root',
data() {
return {
name: 'al'
}
},
methods: {
showInfo(number) {
console.log(number, 'number')
console.log(event, 'event')
console.log('qweqwee')
}
},
})
ps:我记得之前是传递自定义参数之后,函数体内部是接收不到 event 的,需要传递标记位 $event,且在方法形参中接收该参数
<button v-on:click='showInfo(66,$event)'>点击打印信息</button>
showInfo(number, event) {
console.log(number, 'number')
console.log(event.target.innerText, 'event')
console.log('qweqwee')
}
Vue方法内部this指向
<button v-on:click='showInfo'>点击打印信息</button>
const vm = new Vue({
el: '#root',
data() {
return {
name: 'al'
}
},
methods: {
showInfo() {
console.log(this, 'this')
console.log(this === vm)
},
},
})
可以看到,此时的 this 指向的是 Vue 实例
但是如果把 showInfo 改写为 箭头函数,此时,我们就会发现 this现在指向了 window
showInfo: () => {
console.log(this, 'this')
console.log(this === vm)
},
很明显,指向 window 是不合理的,既然是作为 Vue 的配置项,那么就需要受到 Vue 的管理,指向 window 之后,很明显的 脱离了 Vue 的管理,所以,methods 内部的方法,我们都写成原始函数,而弃用箭头函数
Vue 方法在实例中保存的位置
上面简单的说了一下,Vue 的方法 默认写在了 methods 对象内部,那在 vm 实例中,这些方法存在哪里呢?
methods: {
showInfo1() {
console.log(this, 'this')
console.log(this === vm)
},
showInfo2() {
console.log(this, 'this')
console.log(this === vm)
},
},
事实证明,methods 内部的方法 和 data 内部的属性,都是直接挂载到了 vm 实例身上,既然如此,那我就想了,那我的方法能不能直接写在 data 内部,从而丢弃 methods 属性呢?
const vm = new Vue({
el: '#root',
data() {
return {
name: 'al',
showInfo1() {
console.log(this, 'this')
console.log(this === vm)
},
}
},
methods: {
showInfo2() {
console.log(this, 'this')
console.log(this === vm)
},
},
})
分别点击按钮之后,发现两个方法都执行了,但是写在 data 内部的方法,this 指向的是 window,写在 methods 内部的方法,this指向的是 Vue 实例
展开 Vue 实例之后观察
写在 data 内部的 name 属性 和 showInfo1 方法,都存在数据代理的情况,写在 methods 内部的方法,则不存在该情况,那我们就要想一想了,既然放在 data 内部,也可以执行,那为什么还要加 methods 呢?
data 内部的属性我们都已经了解了,是用来做数据代理用的,name 属性其实是和 _data 内部的 name 是互通的,但是一个方法函数,你需要做什么数据代理呢?这个函数在定义之后,只有被调用的时候才会使用到,且函数是不会变的,所以这么看来,函数是根本不需要代理的。
再就是如果将方法写在了 data 内部,那我调用这个方法的时候,还需要去调用 getter 和 setter,根本就没有这个必要,反而造成了大量的数据代理,导致了性能上的浪费。
事件的基本使用总结
- 使用 v-on:xxx 或 @xxx 绑定事件,其中 xxx 则是事件名
- 事件的回调需要配置在 methods 中,且最终会挂载到 vm 实例上
- methods 内部 配置的函数,不能使用箭头函数,否则 this 指向的就不是 Vue 实例了
- methods 内部 配置的函数,都要被 Vue 管理,this 指向的是 vm,或组件实例对象
- @click='demo' 和 @click='demo(123)' 效果一致,但是后者可以传参