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

    根据文件依次向上找

    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。