写文章不容易,点个赞呗兄弟 专一 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工做原理,源码版助于了解内部详情,让咱们一块儿学习吧 研究基于 Vue版本 【2.5.17】node
若是你以为排版难看,请点击 下面连接 或者 拉到 下面关注公众号也能够吧bash
【Vue原理】Event - 源码版 之 绑定组件DOM事件 函数
上一篇已经说了绑定正常标签的原生事件,今天是组件的原生事件,二者最终做用是同样的,可是过程有少少不一样学习
最近更新快是由于文章早就写完了,只是定时发而已哈哈ui
官网已经说明,要是想在组件上绑定原生事件,须要加上 native 修饰符spa
这里同样,解析不是本文重点,只给出结果prototype
如今,我有这么一个模板3d
被解析成这样的渲染函数 code
这个VNode 是 外壳vnode,咱们已经知道外壳 vnode 是保存 父子组件关联的数据cdn
好比 props,事件之类的
因此你在组件上绑定的原生事件,天然而然就是保存在 外壳vnode 上啦
绑定在 外壳vnode 的数据,是要在解析组件内部模板时,才会拿出来使用的
而后!
你能够看到,nativeOn 和 on 都保存有事件
其实解析的时候,只保存在了 nativeOn,on 是 后面 从 nativeOn 直接赋值过去的
打印组件实例能够看到
耶!Vnode 相关又能够看这篇哦
绑定的流程千篇一概,可是有少少出入
能够参考我这篇,绑定原生事件的文章
【Vue原理】Event - 源码版 之 绑定标签DOM事件
相同的地方简单提一下,不一样的地方再仔细说
一、绑定事件发生在 挂载DOM的阶段,从 Vue.prototype._update 开始
二、_update 其中会调用 createElm 来生成DOM
三、createElm 碰到组件,会转去解析组件
function createElm(vnode) {
if (
createComponent(vnode, parentElm, refElm)
) {
return
}
....普通标签的DOM生成和挂载
}
复制代码
进入到 createComponent
function createComponent(vnode, parentElm, refElm) {
var i = vnode.data;
if (isDef(i)) {
// ... 建立组件实例
if (若是组件实例已经建立成功) {
initComponent(vnode);
return true
}
}
}
复制代码
没啥好说的,继续转到了另外一个函数
function initComponent(vnode) {
invokeCreateHooks(vnode);
}
复制代码
而后这个函数仍是为了调用 invokeCreateHooks 这个函数
invokeCreateHooks 上篇文章也出现过,做用是调用各类数据处理函数,好比处理 prop,class 等,其中还包括处理事件的函数 updateDOMListeners
updateDOMListeners 这个函数在上一篇文章中已经说过啦,你们能够看一下 Event - 源码版 之 绑定标签DOM事件
可是我依然给复制源码到这里,可是不写解析
function updateDOMListeners(oldVnode, vnode) {
var on = vnode.data.on || {};
var oldOn = oldVnode.data.on || {};
var target = vnode.elm;
// 遍历绑定的事件
for (name in on) {
newHandler = on[name];
oldHandler = oldOn[name];
// 没有旧事件,就直接添加新事件
if (typeof oldHandler === "undefined") {
// 给事件回调包装一层
target.addEventListener(name, function(){
on[name]() // 执行保存在vnode的事件
});
}
// 新事件和旧事件不同,替换旧事件
else if (newHandler !== oldHandler) {
on[name] = newHandler;
}
}
// 移除旧事件
for (name in oldOn) {
// 旧事件不存在新事件中,直接移除
if (typeof on[name] === "undefined") {
target.removeEventListener(
name, oldOn[name]
);
}
}
}
复制代码