美文网首页VUE
vue利用ul,li实现横向滚动的tab页签

vue利用ul,li实现横向滚动的tab页签

作者: 妮儿_smile | 来源:发表于2021-02-20 13:11 被阅读0次

    效果说明

    导航栏页签是动态加减的,如果页签过多,宽度超过导航栏宽度时需要通过左右两个按钮来实现滚动。


    1613790190979374.gif

    实现原理

    1. ul的css样式设置为不换行(white-space:no-wrap),超出部分隐藏(overflow:hidden)
    2. js找到ul,然后通过scrollTo计算滚动量。

    代码

    <template>
      <div class="com-tab">
        <i class="arrow el-icon-arrow-left" @click="scrollTab('left')"></i>
        <ul id="tab-menu">
          <li :id="'li'+index" v-for="(item,index) in list" :key="index" :class="{
                active: item[idName] === currentName,
              }" @click="tabClick(index,item)">
            {{item[labelName]}}
            <i class="el-icon-close close" @click="tabRemove(item)"></i>
          </li>
        </ul>
        <i class="arrow el-icon-arrow-right" @click="scrollTab('right')"></i>
      </div>
    </template>
    
    <script>
      export default {
        props: {
          list: Array,
          labelName: {
            type: String,
            default: 'label'
          },
          idName: {
            type: String,
            default: 'id'
          },
          value: {},
          activeName: String
        },
        data() {
          return {
            currentName: this.value || this.activeName,
            offsetCount: 0,
          }
        },
        methods: {
          // 点击tab页
          tabClick(index, item) {
            this.setCurrentName(item.id);
            this.$emit('tab-click', item)
          },
          // 删除tab页
          tabRemove(item) {
            this.$emit('tab-remove', item)
          },
          // 设置当前选中tab页
          setCurrentName(value) {
            this.currentName = value;
            this.$emit('input', value);
          },
    
          // 滑动tab页签
          scrollTab(direction) {
            if (this.list.length === 0) return
            let menu = document.querySelector('#tab-menu')
            // 计算ul宽度和当前
            let ulWidth = menu.clientWidth
            const getWidth = (idName) => {
              let li = document.querySelector(idName)
              return li.clientWidth
            }
            let liWidth = 0
            this.list.forEach((ele, index) => {
              liWidth = liWidth + getWidth(`#li${index}`)
            });
            // 根据方向和宽度计算偏移量
            if (liWidth < ulWidth) return
            let distance = this.offsetCount * 100
    
            if (direction === 'left') {
              if (this.offsetCount > 0) {
                this.offsetCount = this.offsetCount - 1
              }
            } else if (direction === 'right') {
              if ((ulWidth + distance) < liWidth) {
                this.offsetCount = this.offsetCount + 1
              }
            }
            distance = this.offsetCount * 100
            menu.scrollTo({
              'left': distance,
              'behavior': 'smooth'
            })
            console.log(distance)
          }
        },
        watch: {
          activeName(val) {
            this.setCurrentName(val)
          },
          value(value) {
            this.setCurrentName(value);
          },
        }
      }
    
    </script>
    
    <style>
      .com-tab {
        padding: 0;
        background: #fff;
        width: 100%;
        display: flex;
      }
    
      .com-tab ul {
        margin: 0;
        padding: 0;
        width: calc(100% - 54px);
        overflow: hidden;
        white-space: nowrap;
      }
    
      .com-tab li {
        background: #f0f8ff;
        list-style: none;
        position: relative;
        display: inline-block;
        padding: 5px 20px 5px 15px;
        border: 1px solid #dad4d8;
        border-right: none;
        cursor: pointer;
        font-size: clamp(12px, 1.1vw, 16px);
      }
    
      .com-tab li:first-child {
        border-left: none;
      }
    
      .com-tab li:last-child {
        border-right: 1px solid #dad4d8;
      }
    
      .com-tab li.active,
      .active>.close {
        background: #fff;
        color: var(--primary-blue)
      }
    
      .close {
        position: absolute;
        top: 2px;
        right: 2px;
        font-size: 8px;
        color: #989ba2;
      }
    
      .arrow {
        font-size: 20px;
        color: #989ba2;
        display: inline-block;
        width: 25px;
        height: 30px;
        border: 1px solid #dad4d8;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
      }
    
    </style>
    
    

    相关文章

      网友评论

        本文标题:vue利用ul,li实现横向滚动的tab页签

        本文链接:https://www.haomeiwen.com/subject/essaxltx.html