使用Ant Design Vue实现Tabs组件滚动吸顶效果
在后台管理系统或长页面场景中,当页面滚动时希望Tabs组件始终固定在顶部,方便用户快速切换标签页,这种效果就是滚动吸顶。结合Ant Design Vue的Tabs组件,我们可以通过监听滚动事件配合样式调整实现该效果,下面介绍具体实现方案。
实现原理
核心思路分三步:
首先获取Tabs组件的初始距离页面顶部的距离
监听页面滚动事件,实时获取当前滚动距离
当滚动距离大于等于Tabs初始顶部距离时,给Tabs添加固定定位样式,小于时移除固定样式
前置准备
确保已经正确安装并引入Ant Design Vue,这里以Ant Design Vue 3.x版本为例,基础引入方式如下:
// main.js
import { createApp } from 'vue'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
import App from './App.vue'
const app = createApp(App)
app.use(Antd)
app.mount('#app')完整实现代码
模板部分
给Tabs组件添加ref引用,方便获取DOM元素,同时定义吸顶状态的响应式变量:
<template>
<div class="page-container">
<!-- 顶部占位内容,模拟长页面上方内容 -->
<div class="top-content">
<h3>页面顶部内容</h3>
<p>这里是页面上方的其他内容,滚动时会先被滚过</p>
<p v-for="item in 10" :key="item">模拟内容行 {{ item }}</p>
</div>
<!-- Tabs组件,绑定ref和吸顶状态 -->
<a-tabs
ref="tabsRef"
v-model:activeKey="activeKey"
:class="{'sticky-tabs': isSticky}"
>
<a-tab-pane key="1" tab="标签页一">
<div class="tab-content">
<p v-for="item in 20" :key="item">标签页一内容 {{ item }}</p>
</div>
</a-tab-pane>
<a-tab-pane key="2" tab="标签页二">
<div class="tab-content">
<p v-for="item in 20" :key="item">标签页二内容 {{ item }}</p>
</div>
</a-tab-pane>
<a-tab-pane key="3" tab="标签页三">
<div class="tab-content">
<p v-for="item in 20" :key="item">标签页三内容 {{ item }}</p>
</div>
</a-tab-pane>
</a-tabs>
<!-- 底部占位内容 -->
<div class="bottom-content">
<p v-for="item in 15" :item">页面底部内容 {{ item }}</p>
</div>
</div>
</template>逻辑部分
在组件挂载时获取Tabs初始位置,监听滚动事件,组件卸载时移除监听避免内存泄漏:
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const activeKey = ref('1')
const tabsRef = ref(null)
const isSticky = ref(false)
let tabsInitialTop = 0
// 处理滚动事件
const handleScroll = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
// 当滚动距离超过Tabs初始顶部距离时,开启吸顶
if (scrollTop >= tabsInitialTop) {
isSticky.value = true
} else {
isSticky.value = false
}
}
onMounted(() => {
// 等待渲染完成后获取Tabs的初始顶部距离
setTimeout(() => {
if (tabsRef.value && tabsRef.value.$el) {
tabsInitialTop = tabsRef.value.$el.getBoundingClientRect().top + window.pageYOffset
}
}, 0)
window.addEventListener('scroll', handleScroll)
})
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
})
</script>样式部分
定义吸顶状态的样式,固定定位在顶部,同时调整层级避免被其他元素覆盖:
<style scoped>
.page-container {
padding: 0 20px;
}
.top-content {
height: 200px;
background-color: #f5f5f5;
padding: 20px;
margin-bottom: 20px;
}
.tab-content {
padding: 20px;
background-color: #fff;
min-height: 300px;
}
.sticky-tabs {
position: fixed;
top: 0;
left: 20px;
right: 20px;
z-index: 999;
background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.bottom-content {
margin-top: 20px;
padding: 20px;
background-color: #f5f5f5;
}
</style>注意事项
获取Tabs初始顶部距离时,需要等待组件渲染完成,因此使用setTimeout放入下一个事件循环,避免出现获取距离为0的问题
吸顶时给Tabs添加左右间距,避免内容贴边影响美观,间距需要和页面容器的padding保持一致
组件卸载时一定要移除scroll事件监听,防止内存泄漏
如果页面有其他固定定位元素,需要调整z-index值,避免层级冲突
效果优化
如果希望吸顶效果有平滑过渡,可以在样式中添加transition属性:
.sticky-tabs {
position: fixed;
top: 0;
left: 20px;
right: 20px;
z-index: 999;
background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}还可以在滚动到Tabs初始位置时,给页面容器添加对应的上边距,避免内容突然跳动,上边距值可以设置为Tabs组件的高度。