vue源码解析之事件机制原理(2)
总的来说。vue初始化的时候,将method中的方法代理到vue[key]的同时修饰了事件的回调函数。绑定了作用域。
2:vue进入compile环节需要将该div变成ast(抽象语法树)。当编译到该div时经过核心函数genHandler:
function genHandler ( name, handler ) { if (!handler) { return 'function(){}' } if (Array.isArray(handler)) { return ("[" + (handler.map(function (handler) { return genHandler(name, handler); }).join(',')) + "]") } var isMethodPath = simplePathRE.test(handler.value); var isFunctionExpression = fnExpRE.test(handler.value); if (!handler.modifiers) { return isMethodPath || isFunctionExpression//假如没有修饰符。直接返回回调函数 ? handler.value : ("function($event){" + (handler.value) + "}") // inline statement } else { var code = ''; var genModifierCode = ''; var keys = []; for (var key in handler.modifiers) { if (modifierCode[key]) { genModifierCode += modifierCode[key];//处理修饰符数组,例如.stop就在回调函数里加入event.stopPropagation()再返回。实现修饰的目的 // left/right if (keyCodes[key]) { keys.push(key); } } else { keys.push(key); } } if (keys.length) { code += genKeyFilter(keys); } // Make sure modifiers like prevent and stop get executed after key filtering if (genModifierCode) { code += genModifierCode; } var handlerCode = isMethodPath ? handler.value + '($event)' : isFunctionExpression ? ("(" + (handler.value) + ")($event)") : handler.value; return ("function($event){" + code + handlerCode + "}") } }
genHandler函数简单明了,如果事件函数有修饰符。就处理完修饰符,添加修饰符对应的函数语句。再返回。这个过程还会单独对native修饰符做特殊处理。这个等会说。compile完后自然就render。我们看看render函数中这块区域长什么样子:
复制代码 代码如下:
_c('div',{attrs:{"id":"test1"},on:{"click":click1}},[_v("click1")]),_v(" "),_c('div',{attrs:{"id":"test2"},on:{"click":function($event){$event.stopPropagation();click2($event)}}}
一目了然。最后在虚拟dom-》真实dom的时候。会调用核心函数:
function add$1 ( event, handler, once$$1, capture, passive ) { if (once$$1) { var oldHandler = handler; var _target = target$1; // save current target element in closure handler = function (ev) { var res = arguments.length === 1 ? oldHandler(ev) : oldHandler.apply(null, arguments); if (res !== null) { remove$2(event, handler, capture, _target); } }; } target$1.addEventListener( event, handler, supportsPassive ? { capture: capture, passive: passive }//此处绑定点击事件 : capture ); }
组件上的事件