petite-vue源码剖析-事件绑定`v-on`的工作原理

vue

在书写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`的工作原理 的全部内容, 来源链接: utcz.com/z/380923.html

回到顶部