记遇到的第一个Vue相关问题:自定义指令

前言

本周的状态:

Yeah! 开始开发Vue3的项目了!
No!对Vue还不太了解...

问题

项目中某功能大致描述:点击某按钮弹出选择框,之后点击其它任一地方收起选择框
emmm... 很简单嘛:

<template>
  <div @click="hideActions">
    <div @click.stop="toggleActions">. . .</div>
    <div v-if="showActions.show">actions</div>
  </div>
</template>

但!在组件外点击时却不能收起选择框,难道需要在所有外层组件捕获onClick事件并且层层传给以上组件?
当然,使用Vuex统一控制也可以,但总感觉不够优雅。

第三方库

经过google,找到了一个库 https://github.com/ndelvalle/v-click-outside
它有两种引入方式:
1、Vue.use(vClickOutside)
2、以指令方式引入

但无论哪种,都是以指令方式使用的

  <div v-click-outside="onClickOutside"></div>

看起来可以解决问题了~

自定义指令

进一步了解这个库,发现是使用自定义指令(custom-directive)实现的

  • 关于自定义指令,可以看官方文档 Vue2 / Vue3,两个版本的差别主要在钩子函数

尝试自己造一个 v-click-outside指令

import { createApp } from 'vue'

const clickoutside = {
  mounted(el, binding) {
    function documentHandler(e) {
      if (el.contains(e.target)) {
        return false
      }
      if (binding.value) {
        binding.value(e)
      }
    }
    el.__vueClickOutside__ = documentHandler
    document.addEventListener('click', documentHandler)
  },
  beforeUnmount(el) {
    // 取消事件监听
    document.removeEventListener('click', el.__vueClickOutside__)
    delete el.__vueClickOutside__
  },
}

const app = createApp(App)
app.directive('clickoutside', clickoutside)
app.mount('#app')

<template>
  <div v-clickoutside="hideActions" >
    <div @click.stop="toggleActions">. . .</div>
    <div v-if="showActions.show">actions</div>
  </div>
</template>

思考

个人感觉自定义指令和React中的高阶组件有一定的相似之处(都针对 组件/元素 进行 生命周期/参数化 相关的注入), 如何从更高的抽象角度去理解这些概念呢?

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容