vue中可以通过@或者v-on的方式绑定事件,也可为其添加修饰符。
new Vue({
el: '#app',
template: `<div @click='divClick'><a @clickt='aClick' href=''>点击</a></div>`,
methods: {
divClick() {
console.log('divClick')
},
aClick() {
console.log('aClick')
},
}
})
以上例子如果点击a会触发其默认行为,如果href不为空还会进行跳转。除此之外,点击还会继续触发div上绑定的点击事件。
如果通过@click.stop.prevent='aClick'的方式为a标签的点击事件添加修饰符stop和prevent,那么就不会触发其a的默认行为,即使href不为空也不会进行跳转,同时,div上的点击事件也不会进行触发。
模板的渲染一般分为编译生成render函数、render函数执行生成vNode和patch进行渲染。下面按照这步骤进行简单分析。
1、render
通过编译生成的render函数:
with(this) {
return _c('div', {
on: {
"click": divClick
}
}, [_c('a', {
attrs: {
"href": "http://www.baidu.com"
},
on: {
"click": function ($event) {
$event.stopPropagation();
$event.preventDefault();
return aClick($event)
}
}
}, [_v("点击")])])
}
其中div的on作为div事件描述。a标签的attrs作为属性描述,on作为事件描述,在描述中.stop被编译成了$event.stopPropagation()来阻止事件冒泡,.prevent被编译成了$event.preventDefault()用来阻止a标签的默认行为。
2、vNode
通过执行Vue.prototype._render将render函数转换成vNode。
3、patch
patch的过程中,当完成$el节点的渲染后会执行invokeCreateHooks(vnode, insertedVnodeQueue)逻辑,其中,针对attrs会将其设置为$el的真实属性,当前例子中会为a标签设置herf属性。针对on会通过target.addEventListener的方式将其处理过的事件绑定到$el上,当前例子中会分别对div和a中的click进行处理,再通过addEventListener的方式进行绑定。
总结
vue中的事件,从编译生成render再通过Vue.prototype._render函数执行render到生成vNode,主要是通过on作为描述。在patch渲染阶段,将on描述的事件进行处理再通过addEventListener的方式绑定到$el上。