vue3+elementuiplus+ts tab 标签页左右滑动
时间: 2023-08-10 07:35:59 浏览: 170
vue左右滑动
在 Vue3 + ElementUI-Plus + TypeScript 中实现 Tab 标签页左右滑动,可以参考以下代码实现:
```html
<template>
<div class="tabs-container">
<el-tabs @tab-click="onTabClick">
<el-tab-pane v-for="(tab, index) in tabs" :key="index" :label="tab.title">
{{ tab.content }}
</el-tab-pane>
</el-tabs>
<div class="tabs-arrow tabs-arrow-left" @click="scroll(-1)">
<i class="el-icon-arrow-left"></i>
</div>
<div class="tabs-arrow tabs-arrow-right" @click="scroll(1)">
<i class="el-icon-arrow-right"></i>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, watch, onMounted } from 'vue'
import { ElTabs, ElTabPane } from 'element-plus'
interface Tab {
title: string
content: string
}
export default defineComponent({
components: {
ElTabs,
ElTabPane
},
setup() {
const tabs = ref<Tab[]>([
{ title: 'Tab 1', content: 'Tab 1 Content' },
{ title: 'Tab 2', content: 'Tab 2 Content' },
{ title: 'Tab 3', content: 'Tab 3 Content' },
{ title: 'Tab 4', content: 'Tab 4 Content' },
{ title: 'Tab 5', content: 'Tab 5 Content' },
{ title: 'Tab 6', content: 'Tab 6 Content' },
{ title: 'Tab 7', content: 'Tab 7 Content' },
{ title: 'Tab 8', content: 'Tab 8 Content' }
])
const scrollRef = ref<HTMLDivElement | null>(null)
const onTabClick = (tab: any) => {
const index = tabs.value.findIndex(item => item.title === tab.props.label)
if (index !== -1) {
const scrollOffset = scrollRef.value?.offsetLeft || 0
const tabOffset = index * 120 // 每个 Tab 的宽度
const diff = tabOffset - scrollOffset
const scrollWidth = scrollRef.value?.offsetWidth || 0
const containerWidth = scrollRef.value?.parentElement?.clientWidth || 0
if (diff + 120 > scrollWidth) {
// 如果当前 Tab 被遮挡,则向右滑动
scrollRef.value?.style?.transform = `translateX(${-(diff + 120 - scrollWidth)}px)`
} else if (diff < 0) {
// 如果当前 Tab 在左侧被遮挡,则向左滑动
scrollRef.value?.style?.transform = `translateX(${Math.max(-tabOffset, 0)}px)`
}
}
}
const scroll = (direction: number) => {
const scrollWidth = scrollRef.value?.offsetWidth || 0
const containerWidth = scrollRef.value?.parentElement?.clientWidth || 0
const scrollOffset = scrollRef.value?.offsetLeft || 0
const minOffsetLeft = containerWidth - scrollWidth
let offsetLeft = scrollOffset + direction * 100
offsetLeft = Math.max(offsetLeft, minOffsetLeft)
offsetLeft = Math.min(offsetLeft, 0)
scrollRef.value?.style?.transform = `translateX(${offsetLeft}px)`
}
watch(tabs, () => {
// 监听 tabs 变化,每次更新后重新计算 Tab 容器的宽度和位置
onMounted(() => {
const scrollWidth = scrollRef.value?.offsetWidth || 0
const containerWidth = scrollRef.value?.parentElement?.clientWidth || 0
if (scrollWidth > containerWidth) {
scrollRef.value?.style?.transform = `translateX(0px)`
} else {
scrollRef.value?.style?.transform = `translateX(${(containerWidth - scrollWidth) / 2}px)`
}
})
})
return {
tabs,
scrollRef,
onTabClick,
scroll
}
}
})
</script>
<style scoped>
.tabs-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.el-tabs__nav-wrap {
display: flex;
flex-wrap: nowrap;
transition: transform 0.3s ease-out;
}
.el-tabs__header {
overflow-x: hidden;
white-space: nowrap;
}
.el-tabs__header .el-tabs__item {
width: 120px;
}
.el-tabs__active-bar {
display: none;
}
.tabs-arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
z-index: 1;
}
.tabs-arrow-left {
left: 10px;
}
.tabs-arrow-right {
right: 10px;
}
</style>
```
在上述代码中,定义了一个 `tabs` 数组,用于存储 Tab 的标题和内容。同时,定义了一个 `scrollRef` 引用,用于获取 Tab 容器的 DOM 元素。
`onTabClick` 方法在 Tab 被点击时触发,通过计算当前 Tab 的位置和容器的位置关系,判断是否需要进行左右滑动。
`scroll` 方法接收一个 direction 参数,代表滑动方向。在方法中,首先获取 `el-tabs__nav-wrap` 元素的宽度、`el-tabs__header` 元素的宽度和 `el-tabs__nav-wrap` 元素的偏移量等信息,然后根据 direction 计算出滑动后的偏移量,最后将偏移量设置为 `el-tabs__nav-wrap` 元素的 transform 属性的值。左右箭头通过绝对定位来实现,点击事件绑定到 `scroll` 方法上。
最后,对 `el-tabs__nav-wrap` 元素和子元素的样式进行自定义,使其能够支持左右滑动。其中,将 `el-tabs__nav-wrap` 元素设置为 flex 布局,并禁用了换行。将 `el-tabs__header` 元素的 overflow-x 属性设置为 hidden,同时将 `el-tabs__item` 元素的宽度设置为 120px(每个 Tab 的宽度),并将 `el-tabs__active-bar` 元素隐藏。
阅读全文