当前位置:   article > 正文

vue3 手写tab栏的滑动效果

vue3 手写tab栏的滑动效果

在tab上定位一个slider,每次点击的时候获取当前active的tab-item序号,从而获取到其相对于父元素的水平距离,然后把这个距离更新到slider的left属性上。

 代码存档↓

  1. <template>
  2. <!-- tab组件封装 -->
  3. <div class="tab" style="margin-top: 10px;" >
  4. <div
  5. class="tab-item" v-for="(item, index) in props.tabData" :key="index"
  6. @click="handleTabChange(index)"
  7. :ref="el => {if(el)tabs[index] = el}"
  8. >
  9. {{ item.label }}
  10. </div>
  11. <div class="slider" :style="`left: ${data.sliderPositionX}px`">{{ data.activeLabel }}</div>
  12. </div>
  13. </template>
  14. <script setup>
  15. import {onMounted, reactive, ref} from 'vue'
  16. //父组件传递来的tab信息
  17. const props = defineProps({
  18. tabData:{
  19. type:Object,
  20. validator: (value) => {
  21. return value.hasOwnProperty('label') && value.label !== ''
  22. }
  23. }
  24. })
  25. const emit = defineEmits(['returnCurrentIndex'])
  26. const data = reactive({
  27. current: 1, //当前被选中的tab-item序号
  28. sliderPositionX: 0, //slider X轴方向位置
  29. windowWidth: window.innerWidth,
  30. activeLabel:''
  31. })
  32. const tabs = ref([])
  33. //更改slider的位置
  34. function updateSliderPosition(){
  35. let activeTab = tabs.value[data.current - 1]
  36. data.sliderPositionX = activeTab.offsetLeft
  37. data.activeLabel = props.tabData[data.current - 1].label
  38. console.log('tab', data.sliderPositionX)
  39. }
  40. function handleTabChange(index){
  41. data.current = index + 1
  42. //向父组件返回当前active tab的序号 方便对页面更新
  43. emit('returnCurrentIndex', data.current)
  44. updateSliderPosition()
  45. }
  46. onMounted(() => {
  47. updateSliderPosition()
  48. window.addEventListener('resize', () => updateSliderPosition());
  49. })
  50. </script>
  51. <style scoped lang="scss">
  52. .tab{
  53. display: flex;
  54. flex-direction: row;
  55. align-items: center;
  56. justify-content: center;
  57. margin-bottom: 10px;
  58. position: relative;
  59. .tab-item{
  60. background-color: #353945;
  61. border: 1px solid #B1B5C3;
  62. color: #B1B5C3;
  63. display: flex;
  64. align-items: center;
  65. justify-content: center;
  66. cursor: pointer;
  67. font-size: 14px;
  68. padding: 8px 16px;
  69. box-sizing: border-box;
  70. width: 95px;
  71. height: 40px;
  72. margin: 0;
  73. }
  74. .tab-item:first-child{
  75. border-radius: 2px 0 0 2px;
  76. }
  77. .tab-item:last-child{
  78. border-radius: 0 2px 2px 0;
  79. }
  80. .slider{
  81. position: absolute;
  82. top: 0;
  83. width: 95px;
  84. height: 40px;
  85. transition: left 0.5s;
  86. box-sizing: border-box;
  87. background: linear-gradient(to right, #F4A58A, #ED6B4E);
  88. color:#000;
  89. border: 1px solid transparent;
  90. display: flex;
  91. align-items: center;
  92. justify-content: center;
  93. }
  94. }
  95. </style>

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/434733
推荐阅读
相关标签
  

闽ICP备14008679号