<template>
<div
class="tab-list"
:style="{ '--translatex': translatex, '--width': width }"
>
<div
v-for="(item, index) in type"
:key="index"
@click="toogleSelect(index)"
class="tab-list-item"
ref="tabRef"
>
{{ item.name }}
</div>
</div>
</template>
<script setup>
import { computed, onMounted, ref, watch } from "vue";
const translatex = ref("0px"); // 滑块滑动位置
const width = ref("0px"); // 滑块宽度
const tabRef = ref(); //tabitem refs
const activeIndex = ref(0); // 切换下标
const type = [{ name: "光标与点按" }, { name: "滚动与缩放" }, { name: "更多手势" }];
// 计算所有tabitem 宽度数组
const widths = computed(() => {
let list = [];
for (const i in tabRef.value) {
list.push(tabRef.value[i].offsetWidth);
}
return list;
});
// 观察切换下标
watch(
() => activeIndex.value,
(val) => {
// 计算滑块的滚动距离
let totalWidth = widths.value.reduce((pre, cur, index) => {
if (index > val - 1) {
return pre + 0;
}
return pre + cur;
}, 0);
translatex.value = totalWidth + "px";
}
);
// tab点击
const toogleSelect = (index) => {
width.value = widths.value[index] + "px";
activeIndex.value = index;
};
onMounted(() => {
// 初始化第一个激活tab的宽度
width.value = widths.value[activeIndex.value] + "px";
});
</script>
<style lang="less">
.tab-list {
height: 28px;
border-radius: 10px;
background: #f3f3f3;
border: 1px solid #d9d9d9;
display: flex;
&-item {
height: 26px;
border-radius: 10px;
line-height: 26px;
padding: 0 15px;
text-align: center;
cursor: pointer;
z-index: 1;
position: relative;
}
&::after {
content: "";
position: absolute;
background-color: #ffffff;
border-radius: 10px;
width: var(--width);
height: 26px;
transform: translateX(var(--translatex));
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
z-index: 0;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);;
}
}
</style>
Vue3 tab switch切换效果 动态计算tab宽度
于 2023-06-23 14:01:13 首次发布