流程
1) 从指令中取出事件名
2) 根据指令的值(表达式)从methods中得到对应的事件处理函数对象
3) 给当前元素节点绑定指定事件名和回调函数的dom事件监听
4) 指令解析完成后,移除此指令属性。
1、是否为元素节点
if (me.isElementNode(node)) { // 判断节点是否为一个元素节点
me.compile(node); // 用来编译元素节点属性 所有的指令的(只要是元素节点就编译)
}
2、进入是节点并且解析指令
compile: function(node) {
var nodeAttrs = node.attributes, // 得到标签的所有的属性节点的伪数组
me = this;
[].slice.call(nodeAttrs).forEach(function(attr) { // 便利所有属性
// 得到属性名: v-on:click
var attrName = attr.name;
if (me.isDirective(attrName)) { // 当前属性名 是指令属性名么?
// 得到属性值--表达式 : show
var exp = attr.value;
// 从属性名中得到指令名: on:click
var dir = attrName.substring(2); // 截取
// 事件指令
if (me.isEventDirective(dir)) { // 是否为事件指令
// 解析解析指令
compileUtil.eventHandler(node, me.$vm, exp, dir);
// 普通指令
} else {
compileUtil[dir] && compileUtil[dir](node, me.$vm, exp);
}
// 移除指令属性
node.removeAttribute(attrName);
}
});
}
3、绑定事件监听
// 事件处理
eventHandler: function(node, vm, exp, dir) { // 事件处理器
var eventType = dir.split(':')[1], // 切分指令名 得到:后的事件名
// 从methods中的到表达式对应的函数
fn = vm.$options.methods && vm.$options.methods[exp]; // 先确保配置了methods 然后去取回调函数
// 如果都存在去做
if (eventType && fn) { // 事件名 和回调函数 才能绑定事件监听
// 给节点绑定指定事件名和回调函数(强制绑定this为vm)的Dom事件监听
node.addEventListener(eventType, fn.bind(vm), false); // 绑定事件监听(通用的) eventType 事件名 bind 返回的是新的函数 特点:this被强制指定为vm,函数体实现与原来的函数的是一模一样的 this被指定为vm
}
}
addEventListener: 是dom2级监听可以绑定多个 v-on 是0级指定绑定一个
一般指令
过程
1)得到指令名和指令值(表达式)
2)从data中根据表达式得到相应的值
3)根据指令名确定需要操作元素节点的什么属性
- v-text—textContent 属性
- v-html—innerHTML 属性
- v-class–classNn 属性
4)将得到的表达式的值设置到相应的属性上
5) 移除元素的指令属性