分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

Vue.js源码——事件机制

发布时间:2023-09-06 01:14责任编辑:蔡小小关键词:js

写在前面

因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出。
文章的原地址:https://github.com/answershuto/learnVue。
在学习过程中,为Vue加上了中文的注释https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以对其他想学习Vue源码的小伙伴有所帮助。
可能会有理解存在偏差的地方,欢迎提issue指出,共同学习,共同进步。

Vue事件API

众所周知,Vue.js为我们提供了四个事件API,分别是$on,$once,$off,$emit。

初始化事件

初始化事件在vm上创建一个_events对象,用来存放事件。_events的内容如下:

{ ???eventName: [func1, func2, func3]}

存放事件名以及对应执行方法。

/*初始化事件*/export function initEvents (vm: Component) { ?/*在vm上创建一个_events对象,用来存放事件。*/ ?vm._events = Object.create(null) ?/*这个bool标志位来表明是否存在钩子,而不需要通过哈希表的方法来查找是否有钩子,这样做可以减少不必要的开销,优化性能。*/ ?vm._hasHookEvent = false ?// init parent attached events ?/*初始化父组件attach的事件*/ ?const listeners = vm.$options._parentListeners ?if (listeners) { ???updateComponentListeners(vm, listeners) ?}}

$on

emit触发。

 ?Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component { ???const vm: Component = this ???/*如果是数组的时候,则递归$on,为每一个成员都绑定上方法*/ ???if (Array.isArray(event)) { ?????for (let i = 0, l = event.length; i < l; i++) { ???????this.$on(event[i], fn) ?????} ???} else { ?????(vm._events[event] || (vm._events[event] = [])).push(fn) ?????// optimize hook:event cost by using a boolean flag marked at registration ?????// instead of a hash lookup ?????/*这里在注册事件的时候标记bool值也就是个标志位来表明存在钩子,而不需要通过哈希表的方法来查找是否有钩子,这样做可以减少不必要的开销,优化性能。*/ ?????if (hookRE.test(event)) { ???????vm._hasHookEvent = true ?????} ???} ???return vm ?}

$once

$once监听一个只能触发一次的事件,在触发以后会自动移除该事件。

 ?Vue.prototype.$once = function (event: string, fn: Function): Component { ???const vm: Component = this ???function on () { ?????/*在第一次执行的时候将该事件销毁*/ ?????vm.$off(event, on) ?????/*执行注册的方法*/ ?????fn.apply(vm, arguments) ???} ???on.fn = fn ???vm.$on(event, on) ???return vm ?}

$off

$off用来移除自定义事件

Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component { ???const vm: Component = this ???// all ???/*如果不传参数则注销所有事件*/ ???if (!arguments.length) { ?????vm._events = Object.create(null) ?????return vm ???} ???// array of events ???/*如果event是数组则递归注销事件*/ ???if (Array.isArray(event)) { ?????for (let i = 0, l = event.length; i < l; i++) { ???????this.$off(event[i], fn) ?????} ?????return vm ???} ???// specific event ???const cbs = vm._events[event] ???/*Github:https://github.com/answershuto*/ ???/*本身不存在该事件则直接返回*/ ???if (!cbs) { ?????return vm ???} ???/*如果只传了event参数则注销该event方法下的所有方法*/ ???if (arguments.length === 1) { ?????vm._events[event] = null ?????return vm ???} ???// specific handler ???/*遍历寻找对应方法并删除*/ ???let cb ???let i = cbs.length ???while (i--) { ?????cb = cbs[i] ?????if (cb === fn || cb.fn === fn) { ???????cbs.splice(i, 1) ???????break ?????} ???} ???return vm ?}

$emit

$emit用来触发指定的自定义事件。

Vue.prototype.$emit = function (event: string): Component { ???const vm: Component = this ???if (process.env.NODE_ENV !== ‘production‘) { ?????const lowerCaseEvent = event.toLowerCase() ?????if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) { ???????tip( ?????????`Event "${lowerCaseEvent}" is emitted in component ` + ?????????`${formatComponentName(vm)} but the handler is registered for "${event}". ` + ?????????`Note that HTML attributes are case-insensitive and you cannot use ` + ?????????`v-on to listen to camelCase events when using in-DOM templates. ` + ?????????`You should probably use "${hyphenate(event)}" instead of "${event}".` ???????) ?????} ???} ???let cbs = vm._events[event] ???if (cbs) { ?????/*将类数组的对象转换成数组*/ ?????cbs = cbs.length > 1 ? toArray(cbs) : cbs ?????const args = toArray(arguments, 1) ?????/*遍历执行*/ ?????for (let i = 0, l = cbs.length; i < l; i++) { ???????cbs[i].apply(vm, args) ?????} ???} ???return vm ?}

关于

作者:染陌

Email:answershuto@gmail.com or answershuto@126.com

Github: https://github.com/answershuto

Blog:http://answershuto.github.io/

知乎主页:https://www.zhihu.com/people/cao-yang-49/activities

知乎专栏:https://zhuanlan.zhihu.com/ranmo

掘金: https://juejin.im/user/58f87ae844d9040069ca7507

osChina:https://my.oschina.net/u/3161824/blog

转载请注明出处,谢谢。

欢迎关注我的公众号

?

Vue.js源码——事件机制

原文地址:http://www.cnblogs.com/answershuto/p/7599321.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved