实现的功能: 点击页面其他地方下拉框消失;
技术栈: vue3+ts
思路: 判断点击的地方是否包含下拉框元素,包含不做处理,不包含且下拉框是展开状态就收起下拉框
dropdown.vue
<template>
<div class="dropdown" ref="dropdownRef">
<a
class="btn btn-secondary dropdown-toggle"
href="#"
role="button"
data-bs-toggle="dropdown"
@click.prevent="handleOpen"
>
{{ props.title }}
</a>
<ul class="dropdown-menu" style="display: block" v-if="isOpen">
<li>新建文章</li>
<li>编辑资料</li>
<li>退出登录</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { defineProps, ref, watch } from 'vue'
import useClickOutside from '@/hooks/useClickOutside'
const props = defineProps({
title: {
type: String,
required: true
}
})
const isOpen = ref(false)
const handleOpen = () => {
isOpen.value = !isOpen.value
console.log(isOpen.value)
}
const dropdownRef = ref<null | HTMLElement>(null) // ref元素
const isClickOutside = useClickOutside(dropdownRef)
// watch 监听是否点击页面其他地方
watch(isClickOutside, () => {
if (isOpen.value && isClickOutside.value) {
isOpen.value = false
}
console.log(isOpen.value)
})
</script>
useClickOutside.ts
import { ref, onMounted, onUnmounted, Ref } from 'vue'
//Ref 获取ref元素
const useClickOutside = (elementRef: Ref<null | HTMLElement>) => {
const isClickOutside = ref(false)
const handler = (e: MouseEvent) => {
if (!elementRef.value?.contains(e.target as HTMLElement)) {
isClickOutside.value = true
} else {
isClickOutside.value = false
}
}
onMounted(() => {
document.addEventListener('click', handler)
})
onUnmounted(() => {
document.removeEventListener('click', handler)
})
return isClickOutside
}
export default useClickOutside