制作京东头部栏切换

57 阅读1分钟

京东App头部栏切换效果

效果图

image.png

父组件

<template>
  <view class="index">
    <view class="tabs_box">
      <Tabs :list="tabList" />
    </view>
  </view>
</template>

<script setup lang="ts">
import Tabs from '@/components/Tabs/Tabs.vue'

const tabList = [
  { label: '首页', id: '0' },
  { label: '小时达', id: '1' },
  { label: '终于完成了', id: '2' }
]
</script>
<style scoped lang="scss">
.index {
  width: 100%;
  min-height: 100vh;
  background-color: antiquewhite;
  .tabs_box {
    display: flex;
    justify-content: center;
    align-items: center;
    padding-top: 100upx;
  }
}
</style>

子组件

<template>
  <view class="tabs">
    <view
      :style="{ width: item.w + 'rpx' }"
      :class="['tabs_item', { active: item.id === tabActive }]"
      v-for="item in tabList"
      :key="item.id"
      @click="tabClick(item.id)"
    >
      {{ item.label }}
    </view>
    <view class="indicator" :style="{ width: tabList[tabActive].w + 'rpx', transform: `translateX(${tabActiveTranslateX})` }"></view>
  </view>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'

interface ITabsProps {
  list: any[]
}

interface ITabList {
  id: string
  w: string
  label: string
}

const props = defineProps<ITabsProps>()
const tabList: ITabList[] | any = ref([])
const tabActive = ref('0') //当前选择的下标
const tabActiveTranslateX = ref('0rpx') //当前选项移动的距离
watch(
  () => props.list,
  (newVal) => {
    tabList.value = newVal.map((i) => {
      return {
        ...i,
        w: i.label.length * 28 + 40
      }
    })
  },
  {
    immediate: true
  }
)
// tab点击回调
const tabClick = (id: string) => {
  if (id === tabActive.value) return

  if (id === '0') {
    tabActive.value = id
    return (tabActiveTranslateX.value = '0rpx')
  }

  // 向右点击
  if (Number(id) > Number(tabActive.value)) {
    let number = 0
    tabList.value.forEach((item: any, index: number) => {
      if (index < Number(id)) {
        number += item.w
      }
    })
    tabActiveTranslateX.value = number + 'rpx'
  }
  // 向左点击
  if (Number(id) < Number(tabActive.value)) {
    tabActiveTranslateX.value = tabList.value[Number(id) - 1].w + 'rpx'
  }

  tabActive.value = id
}
</script>

<style scoped lang="scss">
.tabs {
  padding: 0 10upx;
  background-color: #e90039;
  height: 80upx;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 80upx;
  font-size: 28upx;
  position: relative;
  .tabs_item {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 60upx;
    color: #fff;
    line-height: 60upx;
    border-radius: 60upx;
  }
  .active {
    color: #f82b19;
    z-index: 99;
  }

  .indicator {
    position: absolute;
    left: 10upx;
    height: 60upx;
    border-radius: 60upx;
    background-color: #fbd5de;
    transition: 0.5s;
  }
}
</style>