目录 Vue 自定义指令的执行机制 前情提要 DOM绑定 源码 directive 为什么先调用模版绑定的方法,再调用指令的方法 总结 Vue 自定义指令的执行机制 version: 2.6.14 前情提要 某日,业务需要我
目录
- Vue 自定义指令的执行机制
- 前情提要
- DOM绑定
- 源码
- directive
- 为什么先调用模版绑定的方法,再调用指令的方法
- 总结
Vue 自定义指令的执行机制
version: 2.6.14
前情提要
某日,业务需要我需要在按钮点击之前验证某些条件,如果不符合即不执行click内的业务代码。思前想后,写一个指令不就可以了。做到既不改动原有的业务代码,又可以移植。
<template> <button v-capture @click="handleClick">button</button> </template> <script> export default { methods: { handleClick(){ console.log(1) } }, directives: { capture: { bind(el) { el.captureHandler = (e) => { // 验证条件 console.log(2) e.stopPropagation() }; el.addEventListener("click", el.captureHandler); }, unbind(el) { el.removeEventListener("click", el.captureHandler); } } } } </script>
以上就是伪代码,乍一看没啥问题。
实际一运行,发现1和2都打印出来了,而且1还是在2之前运行的。
这样一看模版上绑定的事件执行是在自定义指令绑定事件之前的。
翻开谷歌,也没有找到相关案例。
DOM绑定
我们都知道vue的SFC最终还是会被编译成js文件,最终模板会被编译成vnode,
元素上绑定的事件会转换成vnode上的一个对象
{ // .... on: { click: 'handleClick' } }
源码
那就找一找这个对象在哪边使用的
runtime中搜索addEventListener
, 因为这个事件绑定上DOM中才有的事件,所以只会在web中了
// src/platforms/web/runtime/modules/events.js export default { create: updateDOMListeners, update: updateDOMListeners, destroy: (vnode: VNodeWithData) => updateDOMListeners(vnode, emptyNode) }
具体实现就先不管
updateDOMListeners
中通过调用了updateListeners
方法,把事件绑定到元素上去
还有就是返回了一个对象,包括create、update、destroy, 这不是很像vue的生命周期函数命名嘛
根据文件依次向上找