Tooltip 组件特性
- 最基础的当鼠标悬浮在目标元素上时,弹出 tooltip 提示信息
- 可以指定 tooltip 弹出位置:placement
- 支持 disable
- 支持手动控制 manual,当开启时,hover 等触发事件失效
- 支持动画
- 支持虚拟触发
实现的基本思路
- popperjs 负责 tooltip 元素的位置计算;
- 通过在 tooltip 元素上绑定
mouseenter
、mouseenter
等事件来控制 tooltip 元素的显示隐藏
学习到的一些写法:
- 针对不同的触发方式,绑定事件:
vue
<template>
<div v-on="events" />
</template>
<script setup>
const events: Ref<Record<string, EventListener>> = ref({});
const outerEvents: Ref<Record<string, EventListener>> = ref({});
const dropdownEvents: Ref<Record<string, EventListener>> = ref({});
function attachEvents() {
if (props.disabled || props.manual) return;
if (props.trigger === "hover") {
events.value["mouseenter"] = openFinal;
outerEvents.value["mouseleave"] = closeFinal;
dropdownEvents.value["mouseenter"] = openFinal;
return;
}
if (props.trigger === "click") {
events.value["click"] = togglePopper;
return;
}
if (props.trigger === "contextmenu") {
events.value["contextmenu"] = (e) => {
e.preventDefault();
openFinal();
};
return;
}
}
</script>
- 对于打开和关闭 tooltip 的函数,添加防抖功能
typescript
let openDebounce: DebouncedFunc<() => void> | void;
let closeDebounce: DebouncedFunc<() => void> | void;
function openFinal() {
// 在打开 Tooltip 时,先取消可能正在进行的关闭操作。
// 这里这样写是因为打开和关闭方法都是 debounce 的,所以需要先取消再执行
closeDebounce?.cancel();
openDebounce?.();
}
function closeFinal() {
// 在关闭 Tooltip 时,先取消可能正在进行的打开操作
// 这里这样写是因为打开和关闭方法都是 debounce 的,所以需要先取消再执行
openDebounce?.cancel();
closeDebounce?.();
}
popperjs
tooltip 的实现用到了 popverjs 这个库,这个库是用于辅助构建提示类工具组件库的,它的基本用法如下:
javascript
const button = document.querySelector('#button');
const tooltip = document.querySelector('#tooltip');
// Pass the button, the tooltip, and some options, and Popper will do the
// magic positioning for you:
Popper.createPopper(button, tooltip, {
placement: 'right',
});
css
实现箭头效果,用了一个正方形,旋转了 45 度方式实现;
css
#arrow,
#arrow::before {
position: absolute;
width: 8px;
height: 8px;
box-sizing: border-box;
background: var(--er-popover-bg-color);
}
#arrow::before {
visibility: visible;
content: '';
transform: rotate(45deg); // 旋转45度
}