在书写petite-vue和Vue最舒服的莫过于通过@click绑定事件,而且在移除元素时框架会帮我们自动解除绑定。省去了过去通过jQuery的累赘。而事件绑定在petite-vue中就是一个指令(directive),和其他指令类似。

深入v-on的工作原理

walk方法在解析模板时会遍历元素的特性集合el.attributes,当属性名称name匹配v-on@时,则将属性名称和属性值压入deferred队列的队尾,当当前元素所有属性绑定和v-modal处理后以及子元素所有属性绑定、v-modal和事件绑定处理后再处理。

那问题来了,为什么要将事件绑定放到最后处理呢?

//文件 ./src/on.ts
const systemModifiers = ['ctrl', 'shift', 'alt', 'meta'] const modifiersGuards: Record<
string,
(e: Event, modifiers: Record<string, true>) => void | boolean
> = {
stop: e => e.stopPropagation(),
prevent: e => e.preventDefault(),
self: e => e.target !== e.currentTarget,
ctrl: e => !(e as KeyedEvent).ctrlKey,
shift: e => !(e as KeyedEvent).shiftKey,
alt: e => !(e as KeyedEvent).altKey,
meta: e => !(e as KeyedEvent).metaKey,
left: e => 'button' in e && (e as MouseEvent).button !== 0,
middle: e => 'button' in e && (e as MouseEvent).button !== 1,
right: e => 'button' in e && (e as MouseEvent).button !== 2,
/* @click.alt.shift 将分别匹配alt和shift两个modifiers guards,当此时按alt+shift+ctrl时,两个modifiers guards均通过。
* 而@click.alt.shift.exact 将分别匹配alt、shift和exact,当此时按alt+shift+ctrl时,前面两个modifiers guards均通过,但最后的exact guard将返回true,不执行事件回调函数。
*/
exact: (e, modifiers) =>
systemModifiers.some(m => (e as any)[`${m}Key`] && !modifiers[m])
} export const on: Directive({ el, get, exp, arg, modifiers }) => {
let handler = simplePathRE.test(exp)
? get(`(e => ${exp}(e)`)
: get(`($event => { ${exp} })`) if (arg === 'vue:mounted') {
// 假如绑定的是生命周期函数mounted,但由于当前元素早已添加到DOM树上,因此将函数压入micro queue执行
nextTick(handler)
return
}
else if (arg === 'vue:unmounted') {
// 假如绑定的是生命周期函数unmounted,则返回cleanup函数
return () => handler()
} if (modifiers) {
// 如果存在modifiers,则对事件绑定进行增强 if (arg === 'click') {
// @click.right 对应的DOM事件是contextmenu
if (modifiers.right) arg = 'contextmenu'
// @click.middle 对应的DOM事件是mouseup
if (modifiers.middle) arg = 'mouseup'
} const raw = hanlder
handler = (e: Event) => {
if ('key' in e && !(hyphenate((e as KeyboardEvent).key) in modifiers)) {
/* 如果为键盘事件,键不在没有在modifiers中指定则不执行事件回调函数
* key值为a、b、CapsLock等,hyphenate将CapsLock转换为caps-lock
*/
return
}
for (const key in modifiers) {
// 执行modifiers对应的逻辑,若返回true则不执行事件回调函数
const guard = modiferGuards[key]
if (guard && guard(e, modifiers)) {
return
}
return raw(e)
}
}
} // 居然没有返回cleanup函数??大家可以去贡献代码了哈哈
listen(el, arg, handler, modifers)
}
//文件 ./src/utils.ts

export const listen = (
el: Element,
event: string,
handler: any,
opotions?: any
) => {
el.addEventListener(event, handler, options)
}

总结

现在我们已经了解了v-bindv-on的工作原理,后面我们一起看看v-modal吧!

petite-vue源码剖析-事件绑定`v-on`的工作原理的更多相关文章

  1. petite-vue源码剖析-双向绑定`v-model`的工作原理

    前言 双向绑定v-model不仅仅是对可编辑HTML元素(select, input, textarea和附带[contenteditable=true])同时附加v-bind和v-on,而且还能利用 ...

  2. jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on

    事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...

  3. 【JQuery源码】事件绑定

    事件绑定的方式有很多种.使用了jQuery那么原来那种绑定方式(elem.click = function(){...})就不推荐了,原因? 最主要的一个原因是elem.click = fn这种方式只 ...

  4. petite-vue源码剖析-属性绑定`v-bind`的工作原理

    关于指令(directive) 属性绑定.事件绑定和v-modal底层都是通过指令(directive)实现的,那么什么是指令呢?我们一起看看Directive的定义吧. //文件 ./src/dir ...

  5. Spark源码剖析(八):stage划分原理与源码剖析

    引言 对于Spark开发人员来说,了解stage的划分算法可以让你知道自己编写的spark application被划分为几个job,每个job被划分为几个stage,每个stage包括了你的哪些代码 ...

  6. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  7. 老李推荐:第6章7节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-注入按键事件实例

    老李推荐:第6章7节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-注入按键事件实例   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜 ...

  8. 老李推荐:第6章5节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-事件

    老李推荐:第6章5节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-事件   从网络过来的命令字串需要解析翻译出来,有些命令会在翻译好后直接执行然后返回,但有 ...

  9. 老李推荐:第5章7节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 循环获取并执行事件 - runMonkeyCycles

    老李推荐:第5章7节<MonkeyRunner源码剖析>Monkey原理分析-启动运行: 循环获取并执行事件 - runMonkeyCycles   poptest是国内唯一一家培养测试开 ...

随机推荐

  1. 「BalkanOI 2018 Day1」Election

    「BalkanOI 2018 Day1」Election 记C为1,T为-1,\(sum[i]\)为\(i\)点的前缀和. 对于询问\([l,r]\),分两步计算答案. 要求所有点的\(sum[i]- ...

  2. Nginx实现跨域配置详解

    主要给大家介绍了关于Nginx跨域使用字体文件的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 问题描述 今天在使用子域名访问根域名的CSS时,发现字体无法显示,在确保CSS和Font字 ...

  3. ubuntu memcached安装与配置

    转载请注明来源:https://www.cnblogs.com/hookjc/ 关于Memcache与memcachedMemcache是项目名,memcached是服务名.让很多初接触的人感觉很是莫 ...

  4. 学习jsp篇:jsp简单实例之二登录

    编程环境:IDEA,Tomcat,JavaEE 一.实例二登录 1.在自己建的工程下的web目录下建一个文件夹为login,在login中编写登录代码(其实就是和实例一同一个项目) 2.先建登录页面j ...

  5. YOLOv5模型训练及检测

    一.为什么使用YOLOv5 二.软件工具 2.1 Anaconda https://www.anaconda.com/products/individual 2.2 PyCharm https://w ...

  6. Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器,包括Spring Security和Spring Boot

    2月14日,Keycloak 团队宣布他们正在弃用大多数 Keycloak 适配器. 其中包括Spring Security和Spring Boot的适配器,这意味着今后Keycloak团队将不再提供 ...

  7. Elasticsearch笔记2

    1 搜索所有文档中还有某个字段的方法: localhost:9200/get-together/group/_search?pretty { "query": { "qu ...

  8. MXNet学习:试用卷积-训练CIFAR-10数据集

    第一次用卷积,看的别人的模型跑的CIFAR-10,不过吐槽一下...我觉着我的965m加速之后比我的cpu算起来没快多少..正确率64%的样子,没达到模型里说的75%,不知道问题出在哪里 import ...

  9. java中的代码块(初始化块)

    介绍 代码块又叫初始化块,属于类中的成员,类似于方法,将逻辑语句封装在方法体中,通过{ } 包围起来,但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不通过对象或类显示调用,而是加载类 ...

  10. figlet 一个在linux生成字符串图案的玩具

    figlet官网 figlet官方字体库 figlet字体样例 安装方法 centos/redhat/fedora 发行版 yum install -y figlet debian/ubuntu 发行 ...