Vue3+TypeScript+Bootstrap 封装自己的下拉框组件

难点:点击下拉框以外的地方关闭下拉框

思路总结:

1.获取下拉框的DOM元素。

2.写一个回调函数,获取当前点击的DOM元素。

3.通过 contains 方法,判断当前点击的DOM元素是否在下拉框DOM元素内来决定是否显示和隐藏下拉框。

<template>
  <div class="dropdown" ref="dropdownRef">
    <a
      class="btn btn-outline-light my-2 dropdown-toggle"
      href="#"
      role="button"
      @click.prevent="toggleOpen" // 点击按钮 改变是否显示下拉框状态
    >
      {{ title }}
    </a>
    <ul
      class="dropdown-menu"
      aria-labelledby="dropdownMenuLink"
      :style="{ display: 'block' }"
      v-if="isOpen" // 是否显示下拉框的标志
    >
      <slot></slot>
    </ul>
  </div>
</template>

<script lang='ts'>
import { defineComponent, ref, watch, onMounted, onUnmounted } from "vue";
import useClickOutside from "../hooks/useClickOutside";
export default defineComponent({
  name: "Dropdown",
  props: {
    title: {
      type: String,
      required: true,
    },
  },
  setup(props) {
    // 通过给标签绑定的 ref 获取 DOM结点
    const dropdownRef = ref<null | HTMLElement>(null);
    const isOpen = ref(false);
    // 点击按钮 显示和隐藏下拉框
    const toggleOpen = () => {
      isOpen.value = !isOpen.value;
    };
     // 点击边框外部隐藏下拉框的回调函数
     const handler = (e: MouseEvent) => {
       // 这层判断必须有,dropdownRef.value 可能是null 而null是没有contains方法的
       // 没有此层 if 判断 if 内部 dropdownRef.value.contains 会报错
       if (dropdownRef.value) {
         console.log(dropdownRef.value);
         // 判断 ref=dropdownRef 的DOM结点中是否包含 当前点击的DOM元素
         if (!dropdownRef.value.contains(e.target as HTMLElement) && isOpen.value ) {
           isOpen.value = false;
         }
       }
     };
    // 生命周期 挂载点击事件
     onMounted(() => {
       document.addEventListener("click", handler);
     });
    // 生命周期,卸载点击事件
     onUnmounted(() => {
       document.removeEventListener("click", handler);
     });

    return {
      isOpen,
      toggleOpen,
      dropdownRef,
    };
  },
});
</script>

<style scoped>
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值