目录
一、组件简介与技术选型
在现代前端开发中,浮层提示组件(Tooltip / Popover)几乎在每个项目中都会用到。我们希望它既能样式灵活,又能交互丰富,还要性能优秀、易于封装。
本次实战将基于以下技术构建高定制提示组件:
- Vue 3:组合式 API + 插槽系统,便于封装弹性强的提示组件;
- Tippy.js:功能完善、主题丰富、交互稳定的轻量弹出库;
- Floating UI:Tippy.js 背后的定位引擎,性能优秀,支持智能翻转、偏移、边界控制等特性。
二、核心功能实现
2.1 安装依赖
npm install @tippyjs/vue@6 tippy.js
2.2 基础封装组件(BaseTooltip.vue)
<!-- components/BaseTooltip.vue -->
<template>
<Tippy
:content="content"
:interactive="interactive"
:placement="placement"
:theme="theme"
:trigger="trigger"
:animation="animation"
:arrow="arrow"
>
<template #default>
<slot />
</template>
<template v-if="$slots.content" #content>
<slot name="content" />
</template>
</Tippy>
</template>
<script setup>
import { Tippy } from '@tippyjs/vue';
defineProps({
content: String,
placement: { type: String, default: 'top' },
theme: { type: String, default: 'light' },
trigger: { type: String, default: 'mouseenter focus' },
animation: { type: String, default: 'shift-away' },
arrow: { type: Boolean, default: true },
interactive: { type: Boolean, default: false },
});
</script>
<style scoped>
.tippy-box[data-theme~='light'] {
background-color: white;
color: black;
border: 1px solid #ddd;
}
</style>
2.3 基本用法
<BaseTooltip content="提示信息">
<button>悬停我</button>
</BaseTooltip>
2.4 插入自定义 HTML 内容
<BaseTooltip interactive>
<template #default>
<button>点击查看</button>
</template>
<template #content>
<div style="padding: 8px">
<h4>Popover 标题</h4>
<p>支持插槽内容</p>
<button @click="handleClick">按钮</button>
</div>
</template>
</BaseTooltip>
<script setup>
function handleClick() {
alert('按钮被点击');
}
</script>
三、功能拓展与优化建议(附实现)
3.1 支持延迟显示和关闭
<BaseTooltip content="延迟提示" :delay="[500, 300]">
<span>鼠标悬停 500ms 后出现</span>
</BaseTooltip>
3.2 支持手动控制浮层显隐
<template>
<button ref="btnRef" @click="showTip">手动触发</button>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import tippy from 'tippy.js';
const btnRef = ref(null);
let instance;
const showTip = () => {
if (instance) {
instance.show();
setTimeout(() => instance.hide(), 2000);
}
};
onMounted(() => {
instance = tippy(btnRef.value, {
content: '这是手动控制的提示',
trigger: 'manual'
});
});
</script>
3.3 响应式提示内容
<script setup>
import { ref } from 'vue';
const tipContent = ref('加载中...');
setTimeout(() => {
tipContent.value = '接口加载完成';
}, 1500);
</script>
<template>
<BaseTooltip :content="tipContent">
<span>动态内容提示</span>
</BaseTooltip>
</template>
3.4 支持图片和图标
<BaseTooltip interactive>
<template #default>
<span>预览图片</span>
</template>
<template #content>
<img src="https://picsum.photos/120/80" alt="图像预览" />
</template>
</BaseTooltip>
3.5 支持关键词提示推荐
<BaseTooltip interactive>
<template #default>
<span>搜索建议</span>
</template>
<template #content>
<ul style="padding: 8px;">
<li>Vue 3</li>
<li>Vite</li>
<li>Tippy.js</li>
</ul>
</template>
</BaseTooltip>
3.6 Popover 中支持交互式内容提交
<BaseTooltip interactive trigger="click">
<template #default>
<button>点击填写</button>
</template>
<template #content>
<form @submit.prevent="submit">
<input v-model="msg" placeholder="输入信息" />
<button type="submit">提交</button>
</form>
</template>
</BaseTooltip>
<script setup>
import { ref } from 'vue';
const msg = ref('');
const submit = () => {
alert('你输入了:' + msg.value);
};
</script>
3.7 支持点击浮层内容进行下载(如导出图片)
<BaseTooltip interactive trigger="click">
<template #default>
<span>点击下载图片</span>
</template>
<template #content>
<img
src="https://picsum.photos/100"
alt="预览图"
style="cursor: pointer"
@click="download"
/>
</template>
</BaseTooltip>
<script setup>
function download() {
const link = document.createElement('a');
link.href = 'https://picsum.photos/100';
link.download = 'preview.jpg';
link.click();
}
</script>
四、封装为插件并全局注册
4.1 tooltip.plugin.ts
import BaseTooltip from '@/components/BaseTooltip.vue';
export default {
install(app) {
app.component('BaseTooltip', BaseTooltip);
}
}
4.2 main.ts 中使用
import TooltipPlugin from './plugins/tooltip.plugin';
app.use(TooltipPlugin);
五、总结
本项目基于 Vue 3 和 Tippy.js 实现了一个高灵活性、主题丰富、插槽支持良好的浮层提示组件,适合用于:
- 基本 Tooltip 提示
- Popover 弹出内容
- 表单浮层、关键词推荐、图像预览等场景
可作为弹出层组件的基础能力,进行下一级封装,如 Popconfirm、Dropdown、ContextMenu、快捷操作工具条等。
到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕