目录 vue可以绑定多个事件吗 第一种 第二种 vue事件绑定的原理 1.1 原生 dom 的绑定 1.2 组件中绑定事件 1.3 $on 是怎么实现的 vue可以绑定多个事件吗 标签绑定一个事件处理函数,然后在相
目录
- vue可以绑定多个事件吗
- 第一种
- 第二种
- vue事件绑定的原理
- 1.1 原生 dom 的绑定
- 1.2 组件中绑定事件
- 1.3 $on 是怎么实现的
vue可以绑定多个事件吗
标签绑定一个事件处理函数,然后在相应的事件处理函数中调用想要触发的多个处理函数
以下两种方案,都可以实施
第一种
<button id="test" @click="test1">按钮</button>
new Vue({ el:"#test", data:"", methods:{ test1:function(){ alert("test1"); this.test2(); this.test3(); }, test2:function(){ alert("test2"); }, test3:function(){ alert("test3"); } } })
第二种
绑定多个事件时,事件之间使用分号“;”分开即可
<el-button type="primary" size="small" @click="add1();add2();">123</el-button>
去methods中添加事件的函数
methods:{ add1(){ console.log(123) }, add2(){ console.log(456) }, }
vue事件绑定的原理
之前我搜这个原理的时候,好多文章,都只写了两句话:
- 原生事件绑定是通过addEventListener绑定给真实元素的。
- 组件事件绑定是通过Vue自定义的key$on实现的。
那具体是怎么实现的呢, 没有说?
就现在具体看一下。
// 原生事件绑定 <div @click="fn()"></div> // 组件绑定 <my-component @click.native="fn" @click="fn1"></my- component>
原理:
事件的编译:
let compiler = require('vue-template-compiler'); //vue-loader let r1 = compiler.compile('<div @click="fn()"></div>'); let r2 = compiler.compile('<my-component @click.native="fn" @click="fn1"></my- component>'); console.log(r1); // {on:{click}} console.log(r2); // {nativeOn:{click},on:{click}}
两者编译出来不一样
// 前者 with (this){return _c('div',{on:{"click":function($event){return fn()}}})} // 后者 with (this){return _c('my-component',{on:{"click":fn1},nativeOn:{"click":function($event){return fn($event)}}})}
1.1 原生 dom 的绑定
- Vue 在创建真是 dom 时会调用 createElm ,默认会调用 invokeCreateHooks
- 会遍历当前平台下相对的属性处理代码,其中就有 updateDOMListeners 方法,内部会传入 add 方法
源码:
function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) { if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) { return } const on = vnode.data.on || {} const oldOn = oldVnode.data.on || {} target = vnode.elm normalizeEvents(on) updateListeners(on, oldOn, add, remove, createOnceHandler, vnode.context) target = undefined } function add ( name: string, handler: Function, capture: boolean, passive: boolean ) { target.addEventListener( // 给当前的dom添加事件 name, handler, supportsPassive ? { capture, passive } : capture ) }
1.2 组件中绑定事件
export function updateComponentListeners ( vm: Component, listeners: Object, oldListeners: ?Object ) { target = vm updateListeners( listeners, oldListeners || {}, add, remove, createOnceHandler, vm) target = undefined } function add (event, fn) { target.$on(event, fn) }
组件绑定事件是通过 vue 中自定义的 $on 方法来实现的
1.3 $on 是怎么实现的
vm.$on( event, callback )
作用:
监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。
原理:
$on是采用了经典的发布订阅者设计模式,首先定义一个事件中心,通过$on订阅事件,将事件存储在事件中心里面,然后通过$emit触发事件中心里面存储的订阅事件。
Vue.prototype.$on = function (event, fn) { const vm: Component = this if (Array.isArray(event)) { for (let i = 0, l = event.length; i < l; i++) { this.$on(event[i], fn) } } else { (vm._events[event] || (vm._events[event] = [])).push(fn) } return vm }
看代码,逻辑很简单,$on函数接收俩个参数,第一个是订阅的事件名,可以是多个,如果是多个就传入一个事件名数组。另一个是回调函数。
首先判断传入的事件是不是一个数组,如果是,那么遍历这个数组,将数组中的每一个事件都递归调用$on方法将其作为单个事件订阅。
如过不是数组,那就当做单个事件名来处理,以该事件名作为key,先尝试在当前实例的_events属性中获取其对应的事件列表,如果获取不到就给其赋空数组为默认值,并将第二个参数回调函数添加进去。
多说一句,实例的_events是什么?这就是在事件初始化的时候,initEvents函数中绑定了_event属性并给其赋值为空对象。这个_events属性就是用来作为当前实例的事件中心,所有绑定在这个实例上的事件都会存储在事件中心_events属性中。
这就是$on的内部原理。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持易盾网络。