ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue轻量级滑动tab栏_选中的item自动居中组件

2020-07-15 10:34:40  阅读:842  来源: 互联网

标签:vue const name content item overflow id 轻量级


可滑动,选定的tabItem自动居中,支持x和y两种模式

<template>
  <div class="scrollBarWrapper" :style="scrollBarWrapperStyle">
    <div
      class="scrollBarContent"
      :class="direction === 'y' ? 'directionY' : 'directionX'"
      ref="scrollBarContent"
    >
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    direction: {
      type: String,
      default: "x",
      validator(value) {
        return value === "x" || value === "y";
      }
    },
    activeIndex: {
      type: Number,
      default: 0,
      validator(value) {
        return value >= 0;
      }
    }
  },
  watch: {
    activeIndex(newVal, oldVal) {
      this.handleChange();
    }
  },
  computed: {
    scrollBarWrapperStyle() {
      return this.direction === "y"
        ? {
            height: "100%"
          }
        : {
            width: "100%"
          };
    }
  },
  mounted() {
    this.initItemDisplay();
    this.handleChange();
  },
  methods: {
    initItemDisplay() {
      const content = this.$refs.scrollBarContent;
      const contentItem = content.children;
      [].forEach.call(contentItem, item => {
        if (this.direction === "y") {
          item.style.display = "block";
        } else {
          item.style.display = "inline-block";
        }
      });
    },
    handleChange() {
      this.$nextTick(() => {
        const content = this.$refs.scrollBarContent; // 发生滑动的元素
        const activeItem = content.children[this.activeIndex]; // 当前选中的元素
        if(!activeItem) return false;
        
        const scrollOption = {
          top: 0,
          left: 0,
          behavior: "smooth"
        };

        if (this.direction === "y") {
          const contentHeight = content.offsetHeight;
          const activeItemHeight = activeItem.offsetHeight;
          const activeItemTop = activeItem.offsetTop;
          const offset = activeItemTop - (contentHeight - activeItemHeight) / 2; // 需要移动的位置
          scrollOption.top = offset;
        } else {
          const contentWidth = content.offsetWidth; // 发生滑动元素的宽
          const activeItemWidth = activeItem.offsetWidth; // 当前元素的宽
          const activeItemLeft = activeItem.offsetLeft; // 当前元素的到他父盒子左侧的距离
          const offset = activeItemLeft - (contentWidth - activeItemWidth) / 2; // 需要移动的位置
          scrollOption.left = offset;
        }

        content.scrollTo(scrollOption);
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.scrollBarWrapper {
  position: relative;
  overflow: hidden;
  user-select: none;
  vertical-align: middle;

  .scrollBarContent {
    width: 100%;
    white-space: nowrap;
    word-break: keep-all;
    -webkit-overflow-scrolling: touch;

    &.directionX {
      overflow-x: scroll;
      overflow-y: hidden;
    }

    &.directionY {
      overflow-x: hidden;
      overflow-y: scroll;
      height: 100%;
    }

    &::-webkit-scrollbar {
      display: none;
    }
  }
}
</style>

demo
<template>
	<scrollBar direction="x" :activeIndex="activeIndex">
		<div
			class="scrollBarItem"
			v-for="(item, index) in options"
			:key="index"
			@click="changeNav(item, index)"
			:class="index === activeIndex ? 'active' : null"
		>
			<div>{{item.name}}</div>
		</div>
	</scrollBar>
</template>
<script>
	// 先导入再注册下
	export default {
		data() {
			return {
				activeIndex: 0,
				options: [
					{id: 1, name: '关注'},
					{id: 2, name: '推荐'},
					{id: 3, name: '本地'},
					{id: 4, name: '新闻'},
					{id: 5, name: '汽车'},
					{id: 6, name: '直播'},
					{id: 7, name: '游戏'},
					{id: 8, name: '小说'},
					{id: 9, name: '美女'}
				]
			}
		},
		methods: {
			changeNav(item, index) {
				this.activeIndex = index;
			}
		}
	}
</script>
<style lang="scss" scoped>
	.scrollBarItem {
		padding: rem(8) rem(15);
	}
	.active {
		color: red;
		div {
			border-bottom: 1px solid red;
		}
	}
</style>

标签:vue,const,name,content,item,overflow,id,轻量级
来源: https://www.cnblogs.com/coderDemo/p/13304051.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有