vue源码解读--event(自定义事件)

目录导航

本节的示例代码如下

vue源码解读--event(自定义事件)_第1张图片

经过上一节对原生事件的分析,我们已经知道了事件parse、codegen、invoker的流程。因此本节对自定义事件只做关键逻辑说明

parse

    我们知道,在parse阶段,当对一个标签完整匹配后将调用parseEndTag执行end调用closeElement进行process作元素的加工,这包括了对标签元素的processAttrs。加工后的ast节点将被标记events对象作为事件描述。故

    父组件ast如下

vue源码解读--event(自定义事件)_第2张图片

    子组件ast如下

vue源码解读--event(自定义事件)_第3张图片

codegen

    我们知道vue会将生成的ast节点转为code,这是一次genElement递归的过程,每一次都会调用gendate执行genHandlers对事件进行处理,并最终将事件描述提取为on对象并作为_c的参数二,故

    父组件的code如下

    子组件的code如下

invoke

    我们知道,一个vue组件在呈现到页面之前,会执行init-mount-render-update-patch等流程。在render过程中其实调用了我们code中的_c去生成vnode,在创建vnode的时候会根据_c的第一个参数(child)确定创建的到底是元素节点还是组件节点

vue源码解读--event(自定义事件)_第4张图片

    由于我们当前的tag不是一个html元素,故将执行到框红的位置去创建组件vnode,根据之前分析,我们知道这将创建一个组件构造器,并在patch阶段对组件执行init。除此之外,还对我们的events做了处理

    这里将我们的事件描述对象on缓存到了listeners上,并将nativeOn替换到了原先的on上。nativeOn只得是我们的原生dom事件,当我们在组件上写.native修饰符时vue将在code阶段在生成nativeOn属性。

    接着便去创建组件的vnode

vue源码解读--event(自定义事件)_第5张图片

    接着便会执行_update,进入父组件的patch流程,在父组件进行createElement过程中将会对组件调用createComponent,执行子组件的创建过程,即init-mount-render-update-patch

vue源码解读--event(自定义事件)_第6张图片

        在子组件的init过程中,将会对配置对象进行一次合并,执行initInternalComponent

vue源码解读--event(自定义事件)_第7张图片

        接着调用initEvents

vue源码解读--event(自定义事件)_第8张图片

    可以看到,框红一的位置取到了我们在创建组件vnode时向listeners保存的事件修饰对象,接着调用updateComponentListeners

vue源码解读--event(自定义事件)_第9张图片
src\core\instance\events.js

    经过上一节的分析,我们知道,updateListeners就是我们事件处理的核心,它将向我们的dom上绑定事件

    但是与上一次不同的是,本次传递的add函数和上一次不一样

    上一次

vue源码解读--event(自定义事件)_第10张图片

    本次

vue源码解读--event(自定义事件)_第11张图片

    也就是说,对于自定义事件,并不是使用addEventListener对dom添加事件的

    我们来看$on的实现,它会将我们的添加到组件vnode的events属性上,key为事件名,value为对应的回调函数

    接着执行$mount,进入子组件的parse和codegen过程,之后进入子组件的update,并最终执行到patch,走到子组件的patch之后,它其实就和我们原生事件是一样的了,故这里忽略掉

invoker

    当点击emit parent时将触发原生事件click触发我们的回调onEmitParent函数,调用this.$emit函数。而this.$emit函数则是在vue原型行定义的,它会拿到我们在$on阶段向组件vnode添加的事件并执行

vue源码解读--event(自定义事件)_第12张图片

你可能感兴趣的:(vue源码解读--event(自定义事件))