vue+eleui项目 项目结构(封装一个全局组件-滚动条)

固定高度表格,然后里面滚动,原生滚动条太难看,而且还有兼容问题,好吧,那就自己写一个吧

<template>
  <div
    class="v-scroll-bar"
    @wheel.prevent="wheelEventHandle"
    :style="{height:height+'px'}"
    ref="jScroll">
    <!--滚动内容-->
    <div class="scroll-content"
      :style="scrollContentStyles">
      <slot></slot>
    </div>
    <!--滚动条-->
    <div
      :class="['scroll-bar-wrap',autoHide?'autoHide':'']"
      :style="scrollWrapStyle"
      @mousedown.prevent.stop="clickBarWrapHandler">
      <div
        ref="bar"
        class="scroll-bar"
        :style="scrollBarStyle"
        @mousedown.prevent.stop="clickBarHandler">
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    name: 'v-scroll-bar',
    props: {
      //  外框高度
      height: {type: Number, default: 100, required: true},
      //  行高
      lineHeight: {type: Number, required: true},
      //  数据的长度
      length: {type: Number, required: true},
      //  速度
      speed: {type: Number, default: 2},
      //自动隐藏
      autoHide: {type: Boolean, default: true},
      //滚动条宽度
      barWidth: {type: Number, default: 6},
      //滚动条跑道颜色
      barWrapColor: {type: String, default: 'transparent'},
      //滚动条颜色
      barColor: {type: String, default: 'rgba(0,0,0,.6)'},
      //圆角
      radius: {type: Number, default: 10},
      //滚动条距离内容的距离
      gap: {type: Number, default: 0},
    },
    data() {
      return {
        //  滚动距离
        scrollTop: 0,
      };
    },
    computed: {
      //  滚动步长  一次滚动多少的距离
      scrollStep() {
        return this.lineHeight / this.speed;
        // return 5;
      },
      //  内容的高度
      scrollHeight() {
        return this.length * this.lineHeight;
      },
      //  可滚动的高度
      useableDistance() {
        return this.scrollHeight - this.height;
      },
      //  滚动内容的样式
      scrollContentStyles() {
        if (this.scrollHeight < this.height) this.scrollTop = 0;
        return {
          transform: `translateY(${this.scrollTop}px)`,
          paddingRight: `${this.gap}px`,
        };
      },
      //  滚动条外框样式
      scrollWrapStyle() {
        return {
          width: `${this.barWidth}px`,
          backgroundColor: this.barWrapColor,
          borderRadius: `${this.radius}px`,
        };
      },
      //  滚动条样式
      scrollBarStyle() {
        this.translateY = (-this.scrollTop * this.height) / this.scrollHeight;

        let translateY = `translateY(${this.translateY}px)`;

        return {
          height: `${this.scrollBarHeight}px`,
          transform: translateY,
          msTransform: translateY,
          webkitTransform: translateY,
          backgroundColor: this.barColor,
          borderRadius: `${this.radius}px`
        };
      },
      //  滚动条高度
      scrollBarHeight() {
        let barHeight = (this.height * this.height) / (this.length * this.lineHeight);
        if (barHeight >= this.height) return 0;
        return barHeight;
      },
    },
    methods: {
      //  滚轮事件处理
      wheelEventHandle(event) {
        let {deltaY} = event;

        if (deltaY > 0) this.prevScorllHandle();
        if (deltaY < 0) this.nextScorllHandle();
      },
      //  向上滚动
      prevScorllHandle() {
        if (-this.useableDistance < this.scrollTop) {
          this.scrollTop -= this.scrollStep;
        }
      },
      //  向下滚动
      nextScorllHandle() {
        if (this.scrollTop < 0) {
          this.scrollTop += this.scrollStep;
        }
      },
      //滑块点击事件
      clickBarHandler(event) {
        event.stopImmediatePropagation();
        document.addEventListener('mousemove', this.mouseMoveDocumentHandler, false);
        document.addEventListener('mouseup', this.mouseUpDocumentHandler, false);
        document.onselectstart = () => false;

        this.yMove = (
          event.currentTarget.offsetHeight - (event.clientY - event.currentTarget.getBoundingClientRect().top)
        );
      },
      //  鼠标移动事件
      mouseMoveDocumentHandler(event) {
        let prevPage = this.yMove;

        if (!prevPage) return;
        let thumbClickPosition = this.$refs['bar'].offsetHeight - prevPage;
        this.barMoveHandle(event, this.$el, thumbClickPosition);
      },
      //  鼠标抬起来的事件
      mouseUpDocumentHandler() {
        this.yMove = 0;
        document.removeEventListener('mousemove', this.mouseMoveDocumentHandler);
        document.onselectstart = null;
      },
      //滑块外框事件
      clickBarWrapHandler(event) {
        let thumbHalf = this.$refs['bar'].offsetHeight / 2;
        this.barMoveHandle(event, event.target, thumbHalf);
      },
      //  滑块移动处理
      barMoveHandle(event, dom, position) {
        let offset = Math.abs(dom.getBoundingClientRect()['top'] - event.clientY);
        let thumbPositionPercentage = (offset - position) * 100 / this.$el.offsetHeight;
        let scrollTop = -(thumbPositionPercentage * this.scrollHeight / 100);

        if (-scrollTop >= this.useableDistance) {
          return this.scrollTop = -this.useableDistance
        } else if (scrollTop >= 0) {
          return this.scrollTop = 0;
        }
        this.scrollTop = scrollTop;
      },
      //  如果有iframe 也需要处理
      iframeDocumentHandle() {
        let iframe = document.getElementsByTagName('iframe');

        if (iframe) {
          for (let i = 0; i < iframe.length; i++) {
            let iframeDocument = iframe[i].contentWindow.document;
            iframeDocument.addEventListener('mouseup', this.mouseUpDocumentHandler, false);
          }
        }
      }
    },

    destroyed() {
      document.removeEventListener('mouseup', this.mouseUpDocumentHandler);
    },
    mounted() {
      this.iframeDocumentHandle();
    }
  };
</script>
<style lang="scss"
  rel="stylesheet/scss"
  scoped>
  .v-scroll-bar {
    width: 100%;
    overflow: hidden;
    position: relative;
    &:hover .autoHide {
      opacity: 1;
    }
    .autoHide {
      opacity: 0;
      transition: all 200ms;
    }
    .scroll-bar-wrap {
      position: absolute;
      top: 0;
      right: 0;
      height: 100%;
      overflow: hidden;
      cursor: pointer;
      .scroll-bar {
        width: 100%;
        cursor: ns-resize;
      }
    }
  }
</style>

猜你喜欢

转载自blog.csdn.net/qq_24510455/article/details/82667898