<template>
<div>
<div ref="triggerSlot">
<slot name="trigger"></slot>
</div>
<div class="tooltip" :style="{ top: `${top}px`, left: `${left}px`, opacity: `${opacity}` }">
<span ref="tipOpacity"><slot></slot></span>
<span class="sanjiao"></span>
</div>
</div>
</template>
<script>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
export default {
name: 'Tooltip',
setup(props, { emit }) {
const top = ref(0);
const left = ref(0);
const triggerSlot = ref(null);
let tipOpacity = ref(null);
let opacity = ref(0);
const handleMouseEnter = () => {
const triggerEl = triggerSlot.value;
console.log('triggerEl', triggerEl.getBoundingClientRect());
if (triggerEl) {
let gsrg = tipOpacity.value.getBoundingClientRect();
const rect = triggerEl.getBoundingClientRect();
top.value = rect.top - rect.height - 30;
left.value = rect.left + (rect.width / 2 - gsrg.width / 2);
}
opacity.value = 1;
};
const handleMouseLeave = () => {
console.log('handleMouseLeave');
opacity.value = 0;
};
onMounted(async () => {
await nextTick(); // 确保DOM已经更新
const triggerEl = triggerSlot.value;
if (triggerEl) {
triggerEl.addEventListener('mouseover', handleMouseEnter);
triggerEl.addEventListener('mouseout', handleMouseLeave);
}
});
onUnmounted(() => {
const triggerEl = triggerSlot.value;
if (triggerEl) {
triggerEl.removeEventListener('mouseover', handleMouseEnter);
triggerEl.removeEventListener('mouseout', handleMouseLeave);
}
});
return {
opacity,
tipOpacity,
top,
left,
triggerSlot,
};
},
};
</script>
<style scoped>
.tooltip {
position: fixed;
z-index: 9;
max-width: 300px;
padding: 10px;
border-radius: 4px;
box-sizing: border-box;
font-size: 13px;
line-height: 1.5;
background: #ffffff;
border: 1px solid #e4e7ed;
}
.sanjiao {
width: 10px;
height: 10px;
position: absolute;
bottom: -5px;
left: 50%;
}
.sanjiao::before {
border-top-color: transparent !important;
border-left-color: transparent !important;
border-bottom-right-radius: 2px;
border: 1px solid #e4e7ed;
background: #ffffff;
right: 0;
position: absolute;
width: 10px;
height: 10px;
z-index: -1;
content: ' ';
transform: rotate(45deg);
box-sizing: border-box;
}
</style>
vue3 自定义tootip组件
最新推荐文章于 2024-05-30 21:53:41 发布