vue 类似tab标题滚动 标签左右滚动

在固定的宽度内,展示不固定标签列表,且每个标签的字数不确定。
在这里插入图片描述

<template>
  <div class="tag-box">
    <div class="tag-list">
      <ul ref="tagList" :style="{left: -nowLeft + 'px'}">
        <li v-for="(item, index) in list" :key="index" :ref="'li'+ index">
          <span
            class="tag"
            :class="{'tag-active': id === item.id}">
            {{ item.tag_name }}
          </span>
        </li>
      </ul>
    </div>
    <a-icon type="left" class="icon-lf" v-show="showLf" @click="handleLeft" />
    <a-icon type="right" class="icon-rt" v-show="showRt" @click="handleRight" />
  </div>
</template>

<script>
export default {
  data () {
    return {
   	  list:[
         { id: 0, tag_name: '全部' },
         { id: 1, tag_name: '其他1' },
         { id: 2, tag_name: '其他2其他2' },
         { id: 9, tag_name: '其他' },
         { id: 3, tag_name: '其他3其他3' },
         { id: 4, tag_name: '其他4其' },
         { id: 5, tag_name: '其他5' },
         { id: 6, tag_name: '其他6其他3' },
         { id: 7, tag_name: '其他7' },
         { id: 8, tag_name: '其他8' }
      ],
      id: 0,
      nowNum: 0, // 滚动了几次
      showLf: false, // 左侧按钮 显隐
      showRt: false, // 右侧按钮 显隐
      allWidth: 0, // 内容总宽
      nowLeft: 0,
      nowIndex: 0 // 显示部分的第一个index
    }
  },
  methods: {
    handleLeft () {
      if (this.nowLeft > 0) {
        this.nowNum--
        this.showRt = true
        if (this.nowNum > 0) {
          let nw = 0
          for (let j = this.list.length; j >= 0; j--) {
            if (j < this.nowIndex) {
              nw += this.$refs['li' + j][0].offsetWidth
              if (nw >= 220) {
                nw -= this.$refs['li' + j][0].offsetWidth
                this.nowLeft -= nw
                this.nowIndex = j + 1
                break
              }
            }
          }
        } else {
          this.nowLeft = 0
          this.nowIndex = 0
          this.showLf = false
        }
      }
    },
    handleRight () {
      if (this.nowLeft + 220 < this.allWidth) {
        this.nowNum++
        this.showLf = true
        let nw = 0
        for (let i = 0; i < this.list.length; i++) {
          if (i >= this.nowIndex) {
            nw += this.$refs['li' + i][0].offsetWidth
            if (nw > 220) {
              nw -= this.$refs['li' + i][0].offsetWidth
              this.nowLeft += nw
              this.nowIndex = i
              break
            }
          }
        }
        if (this.nowLeft + 220 >= this.allWidth) {
          this.showRt = false
        }
      }
    }
  },
  mounted () {
    this.$nextTick(() => {
      this.allWidth = this.$refs.tagList.offsetWidth
      if (this.allWidth > 220) { // 220为固定宽度
        this.showRt = true
      }
    })
  }
}
</script>

<style lang="less" scoped>
  .tag-box{
    width: 260px;
    padding: 0 20px;
    height: 28px;
    position: relative;
    .tag-list{
      width: 220px;
      height: 100%;
      overflow: hidden;
      position: relative;
      ul{
        transition-duration: 0.3s;
        position: absolute;
        top: 0px;
        left: 0px;
        margin: 0;
        padding: 0;
        display: flex;
        flex-wrap: nowrap;
        li{
          white-space: nowrap;
          display: inline-block;
          white-space: nowrap;
          padding: 0 10px;
        }
        li:first-child{
          padding-left: 0;
        }
        li:last-child{
          padding-right: 0;
        }
      }
      .tag{
        cursor: pointer;
        display: inline-block;
        height: 28px;
        line-height: 28px;
        transition: border-color .2s;
        &:hover{
          color: #e72521;
        }
      }
      .tag-active{
        color: #e72521;
      }
    }
    .icon-lf{
      cursor: pointer;
      line-height: 28px;
      position: absolute;
      left: 5px;
      top: 2px;
    }
    .icon-rt{
      line-height: 28px;
      cursor: pointer;
      position: absolute;
      right: 5px;
      top: 2px;
    }
  }
</style>

获取动态ref
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会尽力回答你的问题。首先,你需要在html中创建tab标签和箭头按钮的结构,然后使用Vue编写相应的逻辑。 以下是一个简单的实现示例: HTML结构: ``` <div id="app"> <div class="tab-container"> <div class="tab-scroll"> <ul class="tab-list" :style="{ width: tabWidth + 'px' }"> <li v-for="(tab, index) in tabs" :key="index" :class="{ active: index === currentTab }" @click="selectTab(index)">{{ tab }}</li> </ul> <div class="arrow prev" @click="scrollTabs('prev')" v-if="showPrev"></div> <div class="arrow next" @click="scrollTabs('next')" v-if="showNext"></div> </div> </div> </div> ``` CSS样式: ``` .tab-container { position: relative; overflow: hidden; } .tab-scroll { position: relative; white-space: nowrap; } .tab-list { display: inline-block; padding: 0; margin: 0; list-style: none; } .tab-list li { display: inline-block; padding: 10px; cursor: pointer; } .tab-list li.active { background: #f2f2f2; color: #333; } .arrow { position: absolute; top: 50%; transform: translateY(-50%); width: 30px; height: 30px; background: #ccc; cursor: pointer; } .arrow.prev { left: 0; } .arrow.next { right: 0; } ``` Vue逻辑: ``` new Vue({ el: '#app', data: { tabs: ['Tab 1', 'Tab 2', 'Tab 3', 'Tab 4', 'Tab 5', 'Tab 6', 'Tab 7', 'Tab 8', 'Tab 9', 'Tab 10'], tabWidth: 0, currentTab: 0, showPrev: false, showNext: false }, mounted() { this.calculateTabWidth(); this.checkArrows(); }, methods: { calculateTabWidth() { let tabList = this.$el.querySelector('.tab-list'); let tabs = this.$el.querySelectorAll('.tab-list li'); let tabWidth = 0; tabs.forEach(tab => { tabWidth += tab.offsetWidth; }); this.tabWidth = tabWidth; }, checkArrows() { let tabContainer = this.$el.querySelector('.tab-container'); let tabList = this.$el.querySelector('.tab-list'); if (tabList.offsetWidth > tabContainer.offsetWidth) { this.showNext = true; } else { this.showNext = false; } if (tabList.offsetWidth - tabList.scrollLeft > tabContainer.offsetWidth) { this.showPrev = true; } else { this.showPrev = false; } }, scrollTabs(dir) { let tabContainer = this.$el.querySelector('.tab-container'); let tabList = this.$el.querySelector('.tab-list'); let containerWidth = tabContainer.offsetWidth; let scrollLeft = tabList.scrollLeft; if (dir === 'prev') { this.currentTab--; } else { this.currentTab++; } if (this.currentTab < 0) { this.currentTab = 0; } else if (this.currentTab >= this.tabs.length) { this.currentTab = this.tabs.length - 1; } let tabPos = this.$el.querySelectorAll('.tab-list li')[this.currentTab].offsetLeft; if (tabPos < 0 || tabPos + this.$el.querySelectorAll('.tab-list li')[this.currentTab].offsetWidth > containerWidth) { if (dir === 'prev') { tabList.scrollTo({ left: scrollLeft - this.$el.querySelectorAll('.tab-list li')[this.currentTab].offsetWidth, behavior: 'smooth' }); } else { tabList.scrollTo({ left: scrollLeft + this.$el.querySelectorAll('.tab-list li')[this.currentTab].offsetWidth, behavior: 'smooth' }); } } this.checkArrows(); }, selectTab(index) { this.currentTab = index; this.checkArrows(); } } }); ``` 在这个示例中,我们使用了一个包含所有tab标签的ul元素和两个箭头按钮的div元素。我们使用CSS使这些元素在父容器中水平居中,并将tab标签的列表项设置为inline-block以便它们可以在同一行上排列。 我们使用Vue的数据绑定将tab标签数组、tab列表的宽度、当前选中的标签和箭头按钮的显示状态添加到Vue实例中。我们使用mounted钩子函数计算tab列表的宽度,并检查箭头按钮的显示状态。 我们添加了三个方法:calculateTabWidth用于计算tab列表的宽度,checkArrows用于检查箭头按钮的显示状态,scrollTabs用于滚动到下一个或前一个tab标签。在scrollTabs函数中,我们首先根据箭头按钮的方向滚动到下一个或前一个标签,并将currentTab变量更新为相应的标签。然后,我们计算新的tab标签位置,并检查它是否在容器中可见。如果不是,则使用scrollTo方法滚动到新标签。最后,我们调用checkArrows方法来检查箭头按钮的显示状态。 我们还添加了selectTab方法,用于在单击tab标签时更新currentTab变量,并调用checkArrows方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值