当前位置: 首页 > Web前端 > HTML

Vue源码解读(七)——Hook事件

时间:2023-03-28 20:06:11 HTML

当学习成为习惯,知识就成为常识。感谢您的关注、点赞、收藏和评论。有新视频和文章会第一时间发到微信公众号。欢迎关注:李永宁lyn的文章已收录到github仓库liyongning/blog。欢迎收看星空。前言HookEvent(钩子事件)相信很多Vue开发者都没有用过,甚至没有听说过。毕竟Vue官方文档中并没有提到。Vue提供了一些生命周期钩子函数供开发者在特定的逻辑点添加额外的处理逻辑,例如:提供了两个生命周期钩子beforeMount和mounted,供开发者在组件挂载阶段执行额外的逻辑处理,比如准备挂载所需的数据渲染到组件。那么这个HookEvent——钩子事件,也就是钩子的意思,跟Vue的生命周期钩子函数有什么关系呢?它有什么用?这是本文要回答的问题。目标是了解什么是HookEvent?了解它的使用场景,深入理解HookEvent的实现原理什么是HookEvent?HookEvent是Vue的自定义事件结合生命周期钩子实现的功能,用于从组件外部向组件注入额外的生命周期方法。使用场景假设现在有这么一个第三方业务组件,逻辑很简单,调用接口获取挂载生命周期中的数据,然后将数据渲染到页面即可。然后我发现这个组件有一些缺陷,比如最简单的界面等待时间可能比较长。我想在mounted生命周期开始执行的时候,在控制台输出一个loading...字符串,来提升用户体验。如何实现这个要求?有两种方式:第一种比较麻烦,修改源码;而第二种方式就简单多了,就是我们今天介绍的HookEvent,从组件外部向组件注入额外的生命周期方法。这个时候你就会发现当你刷新页面当业务组件请求数据时,它会在控制台输出一个loading...字符串。函数HookEvent的作用是什么?可以通过HookEvent从组件外部将额外的生命周期方法注入到组件中。实现原理了解HookEvent的使用场景和作用,再从源码中寻找它的实现原理,做到“知其然,知其所以然”。前面提到HookEvent是Vue的自定义事件结合生命周期钩子函数实现的功能,那么我们来看一下生命周期相关的代码,例如:我们知道Vue的生命周期函数是通过一个叫做callHook方法的函数来执行callHook/src/core/instance/lifecycle.js/***callHook(vm,'mounted')*执行实例指定的生命周期钩子函数*如果实例设置了对应的HookEvent,例如:,执行生命周期函数后,触发执行事件*@param{*}vm组件实例*@param{*}hook生命周期钩子函数*/exportfunctioncallHook(vm:Component,hook:string){//在执行生命周期钩子函数时禁用依赖收集//#7573在调用生命周期钩子时禁用dep收集pushTarget()//从实例配置对象中获取指定的钩子函数,例如mountedconsthandlers=vm.$options[hook]//挂载钩子constinfo=`${hook}hook`if(handlers){//通过invokeWithErrorHandler执行生命周期钩子for(leti=0,j=handlers.length;我,则传$emit触发此事件//vm._hasHookEvent标识组件是否有hook事件,在vm.$on中处理组件自定义事件时设置if(vm._hasHookEvent){//vm.$emit('hook:mounted')vm.$emit('hook:'+hook)}//关闭依赖集合popTarget()}invokeWithErrorHandling/src/core/util/error.js/***通用函数,执行指定的函数handler*传入的函数会用trycatch包裹处理异常*/exportfunctioninvokeWithErrorHandling(handler:Function,context:any,args:null|any[],vm:any,info:string){letrestry{//执行传入的函数handler,并将执行结果返回给res=args?handler.apply(context,args):handler.call(context)if(res&&!res._isVue&&isPromise(res)&&!res._handled){res.catch(e=>handleError(e,vm,info+`(Promise/async)`))//issue#9511//避免在嵌套调用时多次触发catchres._handled=true}}catch(e){handleError(e,vm,info)}returnres}vm.$on/src/core/instance/events.js/***在实例上监听自定义事件,vm._event={eventName:[fn1,...],...}*@param{*}eventA单个事件名或多个事件名数组*@param{*}fn触发事件时执行的回调调用函数*@returns*/Vue.prototype.$on=function(event:string|Array,fn:Function):Component{constvm:Component=thisif(Array.isArray(event)){//event是由多个事件名组成的数组,遍历这些事件,依次递归调用$onfor(leti=0,l=event.length;i在处理组件自定义事件(vm.$on)时,如果发现组件有hook:xx格式的事件(xx是Vue的生命周期函数),然后vm._hasHookEvent被设置为true,这意味着该组件有一个HookEvent。当组件生命周期方法被触发时,这些生命周期函数将通过callHook方法在内部执行。生命周期函数执行完后,如果发现vm._hasHookEvent为真,则说明当前组件有HookEvent,HookEvent的执行由vm.$emit('hook:xx')触发。这就是HookEvent的实现原理。支持视频链接,微信公众号回复:《精通Vue技术栈源码原理视频版》获取精通Vue技术栈源码原理专栏github仓库liyongning/Vue欢迎Star谢谢大家的关注、点赞、收藏和意见,我们下期见。当学习成为一种习惯,知识就成为常识。感谢您的关注、点赞、收藏和评论。有新视频和文章会第一时间发到微信公众号。欢迎关注:李永宁lyn的文章已收录到github仓库liyongning/blog。欢迎收看星空。