Vue点击div按钮使其具备自动居中功能

1.写一个支持滑动的组件scroll.vue

<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 / 3; // 需要移动的位置
            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="less" 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>
  

2.在需要使用滑块的页面引用这个组件,支持横向及纵向滑动

<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: '新闻'},
				]
			}
		},
		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>