实现效果
实现思路
- 记录滚动容器、滚动项的ref
- 点击某一项tab时,滚动对应项到界面上
- 监听滚动容器滚动,计算展示在界面的滚动项,选中对应tab项
关键代码
html
<a-tabs id="template-tab" v-model:activeKey="activeKey" tab-position="left" @change="onChangeTab"><a-tab-pane v-for="tab in tabs" :key="tab.value" :tab="tab.name"></a-tab-pane>
</a-tabs>
<div ref="scrollEl"><divv-for="(list, index) in ListByTab":ref="(res) => setTabListRef(index, res)":key="index"></div>
<div>
ts
const activeKey = ref<number>(0);
const tabs = ref([{ ...defaultTab }]);
const tabListRefs = ref<any[]>([]);
const scrollEl = ref();
const { y } = useScroll(scrollEl);
const ListByTab = ref<Item[][]>([[]]);
const tabChanging = ref<boolean>(true);function onChangeTab(tabKey: number) {tabChanging.value = false;keyword.value = '';nextTick(() => {let el = tabListRefs.value[tabKey]?.$el;if (tabListRefs.value[tabKey] instanceof HTMLElement) {el = tabListRefs.value[tabKey];}el?.scrollIntoView?.({ block: 'start' });tabChanging.value = true;});
}function setTabListRef(index: number, res: any) {tabListRefs.value[index] = res;
}
const updateActiveTab = throttle(() => {const { top: scrollTop, height: scrollHeight } = scrollEl.value.getBoundingClientRect();for (const [index, el] of tabListRefs.value.entries()) {let realEl: any;if (el instanceof HTMLElement) {realEl = el;} else {realEl = el?.$el;}if (realEl) {const { top, height } = realEl.getBoundingClientRect();if (top + height > scrollTop + scrollHeight * 0.66 || top >= scrollTop) {if (activeKey.value === index) {break;} else {const leftTabElement = document.getElementById('template-tab');if (leftTabElement) {const divElements = leftTabElement.querySelectorAll('div');divElements.forEach((element: any) => {element.blur(); });}activeKey.value = index;break;}}}}
}, 500);watch(() => y.value,() => {if (tabChanging.value) {updateActiveTab();}},
);