美文网首页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