Vue2 模版指令元素绑定事件执行顺序解析

来自:网络
时间:2022-12-31
阅读:
目录

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的生命周期函数命名嘛

根据文件依次向上找

返回顶部
顶部