ToC
修饰符代表了什么
在 vue 开发中时常会看到 .stop
.prevent
.capture
等事件修饰符,这些修饰符是如何被实现的呢?首先我们知道,事件修饰符是在编译阶段被处理的,所以我们需要从编译阶段开始看起。以 Vue2 为例,我们很容易就可以找到这段代码,它在 src/compiler/codegen/events.ts. 修饰符的定义如下:
修饰符是如何生效的
可以看到,这里的修饰符除了 .stop
和 .prevent
之外都会通过 genGuard
函数生成一个运行时的判断条件。比如 .stop
和 .prevent
修饰符,这俩是直接插入 $event.stopPropagation();
和 $event.stopPropagation();
到最终生成的代码里,而其他的修饰符则会根据修饰符的进行变化。比如 .ctrl
,生成的条件就是 if(!$event.ctrlKey)
, 其他的以此类推,如果条件为 true
,则返回 return null
,否则返回空字符串。为什么需要显式 return null
,也在注释中说明了原因:
modifiers that prevent the execution of the listener need to explicitly return null so that we can determine whether to remove the listener for .once
防止侦听器执行需要明确返回null的修饰符,以便我们确定是否删除了侦听器。
这里的 $event
是一个参数,它是在 src/compiler/codegen/events.ts 处,由 genHandler
方法生成的,它其实表示的是一个形参,会在编译的时候包装一个新的函数,然后传入到包装的函数内部。额外包装一个函数是为了确保这个事件处理句柄一定是一个函数,而不是类似 test(1,2,3)
这一类函数调用的表达式。
处理所有事件类型
genHandlers()
的代码比较简单,主要是处理了动态事件名和动态事件句柄,就不做详细解析了:
事件处理函数的生成
我们重点看一下 genHandler()
函数的实现:
修饰符的按键如何映射到键盘的keyCode
同时还有 genKeyFilter
函数, 用来生成对按下的按键的判断的 if 代码, 以及 genFilterCode
函数, 用来生成对按下的按键 code 的代码。
_k() 与 _d() 方法的实现
_k()
方法的实际实现如下,在 此处 有对其进行赋值target._k = checkKeyCodes
,主要用于判断按键是否匹配,_d()
函数则是用于处理动态事件名的: target._d = bindDynamicKeys
,代码量比较少,处理的分支情况页不多,直接看代码吧:
以上。