返回

内外结合,妙用Vue3+TS实现自定义指令v-click-outside

前端

简介:何谓v-click-outside?

在前端开发中,我们时常会遇到这样的场景:需要创建一个浮层来展示一些不常用信息,但当我们点击浮层之外的区域时,希望该浮层能够自动关闭。这时,v-click-outside指令便派上了用场。

认识v-click-outside指令

v-click-outside指令,顾名思义,是一个Vue指令,允许我们在元素之外的任何位置侦听点击事件。当点击事件发生时,指令将触发相应的回调函数,我们可以通过该回调函数来执行所需的逻辑。

开发v-click-outside指令

Step 1:项目创建

首先,让我们创建一个新的Vue3项目,并安装TypeScript。

vue create my-project --use-typescript

Step 2:编写指令代码

接下来,在src/directives目录下创建一个新的文件v-click-outside.ts,并输入以下代码:

import { DirectiveBinding, ObjectDirective } from 'vue';

// 定义指令对象
const clickOutside: ObjectDirective = {
  mounted(el, binding) {
    // 获取指令绑定的回调函数
    const handler = binding.value;

    // 绑定click事件监听器
    const listener = (event: Event) => {
      // 判断点击位置是否在元素之外
      if (!el.contains(event.target as HTMLElement)) {
        // 若在元素之外,触发回调函数
        handler();
      }
    };

    // 将事件监听器添加到文档中
    document.addEventListener('click', listener);

    // 指令销毁时,移除事件监听器
    el.__vueClickOutside__ = listener;
  },
  unmounted(el) {
    // 移除事件监听器
    document.removeEventListener('click', el.__vueClickOutside__);
  },
};

export default clickOutside;

Step 3:在main.ts中注册指令

src/main.ts文件中,将v-click-outside指令注册为全局指令:

import { createApp } from 'vue';
import App from './App.vue';
import clickOutside from './directives/v-click-outside';

const app = createApp(App);

// 注册指令
app.directive('click-outside', clickOutside);

app.mount('#app');

实战案例:构建一个功能完善的dropdown组件

现在,让我们使用v-click-outside指令来构建一个dropdown组件。

Step 1:创建dropdown组件

src/components目录下创建一个新的文件dropdown.vue,并输入以下代码:

<template>
  <div class="dropdown">
    <button @click="toggleDropdown">{{ buttonText }}</button>
    <ul v-click-outside="closeDropdown" v-if="dropdownOpen">
      <li v-for="item in items" :key="item">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const buttonText = ref('Dropdown');
    const dropdownOpen = ref(false);
    const items = ['Item 1', 'Item 2', 'Item 3'];

    const toggleDropdown = () => {
      dropdownOpen.value = !dropdownOpen.value;
    };

    const closeDropdown = () => {
      dropdownOpen.value = false;
    };

    return {
      buttonText,
      dropdownOpen,
      items,
      toggleDropdown,
      closeDropdown,
    };
  },
};
</script>

<style>
.dropdown {
  position: relative;
}

.dropdown button {
  padding: 10px;
  background-color: #333;
  color: #fff;
  border: none;
  border-radius: 5px;
}

.dropdown ul {
  position: absolute;
  top: 100%;
  left: 0;
  padding: 10px;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 5px;
  display: none;
}

.dropdown ul li {
  padding: 5px;
  cursor: pointer;
}

.dropdown ul li:hover {
  background-color: #f5f5f5;
}

.dropdown.open ul {
  display: block;
}
</style>

Step 2:在App.vue中使用dropdown组件

src/App.vue文件中,将dropdown组件添加到模板中:

<template>
  <div>
    <dropdown></dropdown>
  </div>
</template>

<script>
import Dropdown from './components/dropdown.vue';

export default {
  components: {
    Dropdown,
  },
};
</script>

现在,当您点击dropdown按钮时,下拉列表将打开。当您点击下拉列表之外的区域时,下拉列表将自动关闭。

结语

通过结合Vue3和TypeScript,我们可以创建出功能强大的自定义指令,v-click-outside就是一个很好的例子。这种指令可以帮助我们轻松地实现元素之外的点击事件处理,从而构建出更加交互式的用户界面。