效果图如下:
录屏如下:
tabs录屏
控件用法如下:
<navi-tabs :data="tabs" @changeTab="changeTab"></navi-tabs>import NaviTabs from "@/components/navi-tabs";components: { NaviTabs },tabs: [{ codeName: "菜单1" },{ codeName: "菜单2" },// { codeName: "菜单..." },{ codeName: "菜单N" },
],
currentTabIndex: 0,changeTab(index) {this.currentTabIndex = index;// this.refreshTargetTabPage();
},
控件源码如下:
<template><div class="tabs-root"><div class="tabs-container"><div class="tabs" ref="tabs" v-if="data && data.length > 0"><div class="item" v-for="(tab, index) in data" :key="index":class="activeIndex == index ? 'active': ''"@click="setActiveIndex(index)">{{ tab.codeName }}</div></div></div></div>
</template><script>
export default {props: {data: {type: Array,default: [],},},data() {return {activeIndex: 0, // 默认激活的tab索引};},mounted() {this.scrollToActiveTab(); // 初始化时也滑动到第一个tab},methods: {setActiveIndex(index) {this.activeIndex = index;this.$emit("changeTab", index);this.scrollToActiveTab(); // 调用滑动函数},scrollToActiveTab() {this.$nextTick(() => {if (this.activeIndex == 0) {tabs.scrollTo({ left: 0, behavior: 'smooth' });return;}const tabs = this.$refs.tabs;const tabsRect = tabs.getBoundingClientRect();const activeTab = tabs.children[this.activeIndex];const activeTabRect = activeTab.getBoundingClientRect();let widthBeforeAll = 0;for (let index = 0; index < this.activeIndex; index++) {const element = tabs.children[index];const elementsRect = element.getBoundingClientRect();widthBeforeAll += elementsRect.width;}const offSetX = widthBeforeAll + (activeTabRect.width / 2) - (tabsRect.width / 2);tabs.scrollTo({ left: (tabsRect.left / 2 + offSetX), behavior: 'smooth' });});}},
};
</script>
<style lang="scss" scoped>.tabs-root {width: 100%;height: 44px;display: flex;justify-content: center;.tabs-container {width: auto;height: 100%;overflow-x: hidden;overflow-y: hidden;.tabs {display: flex;flex-direction: row;align-items: center;overflow-x: auto;.item {min-width: 120px;height: 26px;margin-top: 9px;margin-bottom: 9px;margin-right: 9px;cursor: pointer;white-space: nowrap;font-family: PingFangSC-Semibold;font-size: 18px;color: #FFFFFF;text-align: center;line-height: 26px;font-weight: 600;background: #C70019;border-radius: 13px;}.active {background: #DD6675;}}}}
</style>