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
);
}
组件上的事件
