参照element-ui的el-scroll自己实现了一个自定义组件,代码如下:

  

<template>
  <div class="c-scroll-box" ref="scrollBox"  unselectable="on" onselectstart="return false;" style="-moz-user-select:none;">
    <div class="c-scroll-container" @scroll="containerScroll" ref="scrollContainer">
      <div class="c-scroll-view" ref="scrollViewBox">
        <slot></slot>
      </div>
    </div>
    <!-- 右侧滚动条 -->
    <div class="c-scroll-vertical-box c-scroll-bar" :style="verticalStyle" ref="verticalBox" @mousedown="vBoxDown"></div>
    <!-- 下方滚动条 -->
    <!-- <div class="c-scroll-horizontal-box c-scroll-bar" :style="horizontalStyle" ref="horizontalBox"></div> -->
  </div>
</template>
<script>
import { domResize } from "./domResize.js";
export default {
  data() {
    return {
      verticalStyle: {
        height: "60px",
        top: 0,
        transform: 'translateY(0)'
      },
      horizontalStyle: {
        width: "10px",
        left: 0
      },
      viewHeight: 0,
      viewWidth: 0,
      vBarPageY: 0,
      vBarTranslateY: 0,
      hBarPageX: 0,
      vMouseFlag: false
    };
  },
  watch: {},
  mounted() {
    this.domResizeListener();
  },
  methods: {
    /**
     * @name vBoxDown
     * @description 竖直滚动条鼠标按下
     * @author cjs1992
     * @date 2018-10-25 13:57
     */
    vBoxDown(event) {
      document.removeEventListener("mousemove", this.vBoxMove);
      document.removeEventListener("mouseup", this.vBoxUp);
      this.vBarPageY = event.pageY;
      this.vMouseFlag = true;
      document.addEventListener("mousemove", this.vBoxMove);
      document.addEventListener("mouseup", this.vBoxUp);
    },
    /**
     * @name vBoxUp
     * @description 竖直滚动条鼠标放开
     * @author cjs1992
     * @date 2018-10-25 13:57
     */
    vBoxUp(event) {
      event.preventDefault();
      event.stopPropagation()
      this.vMouseFlag = false;
    },
    /**
     * @name vBoxMove
     * @description 竖直滚动条鼠标移动
     * @author cjs1992
     * @date 2018-10-25 13:57
     */
    vBoxMove(event) {
      if (!this.vMouseFlag) {
        return;
      }
      let scrollBox = this.$refs.scrollBox;
      let verticalBox = this.$refs.verticalBox;
      let scrollContainer = this.$refs.scrollContainer;
      let scrollViewBox = this.$refs.scrollViewBox;
      let num = event.pageY - this.vBarPageY;
      this.vBarPageY = event.pageY;
      // let t_top = parseFloat(this.verticalStyle.top) + num;
      /**>>>> */
      let t_top = parseFloat(this.vBarTranslateY) + num;

      let max_top =
        scrollBox.clientHeight - parseFloat(this.verticalStyle.height);
      // 判断是否超出滚动范围
      if (t_top <= 0) {
        t_top = 0;
      } else if (max_top <= t_top) {
        t_top = max_top;
      }
      // this.verticalStyle.top = t_top + "px";
      /**>>>>>> */
      this.verticalStyle.transform = "translateY(" + t_top + "px)";
      this.vBarTranslateY = t_top;
      if (scrollContainer.scrollTo) {
        scrollContainer.scrollTo(
        this.horizontalStyle.left,
        (t_top * scrollViewBox.clientHeight) / scrollBox.clientHeight
      );
      } else {
        scrollContainer.scrollTop = (t_top * scrollViewBox.clientHeight) / scrollBox.clientHeight;
      }
    },
    /**
     * @name containerScroll
     * @description scroll
     */
    containerScroll() {
      let scrollContainer = this.$refs.scrollContainer;
      let scrollBox = this.$refs.scrollBox;
      let scrollViewBox = this.$refs.scrollViewBox;
      // this.verticalStyle.top =
      //   (scrollBox.clientHeight * scrollContainer.scrollTop) /
      //     scrollViewBox.clientHeight +
      //   "px";
      /**>>>>>> */
      this.verticalStyle.transform = "translateY(" + (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight + "px)";
      this.vBarTranslateY = (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight;
    },
    /**
     * @name setBarHeight
     * @description 获取滚动条高度
     * @author cjs1992
     * @date 2018-10-25 10:56
     */
    setBarHeight() {
      let scrollBox = this.$refs.scrollBox;
      let scrollViewBox = this.$refs.scrollViewBox;
      let scrollContainer = this.$refs.scrollContainer;
      // 滚动条的高度
      let rate = scrollBox.clientHeight / scrollViewBox.clientHeight;
      if (rate >= 1) {
        this.verticalStyle.height = 0;
      } else {
        this.verticalStyle.height = scrollBox.clientHeight * rate + "px";
        // 计算滚动条的位置
        // this.verticalStyle.top =
        //   (scrollBox.clientHeight * scrollContainer.scrollTop) /
        //     scrollViewBox.clientHeight +
        //   "px";
        /**>>>>>> */
      this.verticalStyle.transform = "translateY(" + (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight + "px)";
      this.vBarTranslateY = (scrollBox.clientHeight * scrollContainer.scrollTop) / scrollViewBox.clientHeight;
      }
    },
    /**
     * @name domResizeListener
     * @description dom元素的resize方法
     * @author cjs1992
     * @date 2018-10-25 11:34
     *  */
    domResizeListener() {
      domResize(this.$refs.scrollViewBox, ele => {
        if (ele) {
          let { contentRect: cont } = ele;
          if (cont.height !== this.viewHeight) {
            this.viewHeight = cont.height;
            this.verticalBarChange();
          } else if (cont.width !== this.viewWidth) {
          }
        }
      });
    },
    /**
     * @name verticalVBarChange
     * @description 右侧滚动条变化事件
     */
    verticalBarChange() {
      this.setBarHeight();
    },
    /**
     * @name horizontalBarChange
     * @description 底部滚动条变化事件
     */
    horizontalBarChange() {
      console.log(this.viewWidth);
    }
  }
};
</script>
<style scoped>
.c-scroll-box {
  /* width: 100%; */
  height: 100%;
  overflow: hidden;
  box-sizing: border-box;
  position: relative;
}
.c-scroll-container {
  /* width: 100%; */ /*请注意,这里不能width: 100%;如果需要设置margin-right: -17px的话*/
  height: 100%;
  margin-right: -17px;
  margin-bottom: -17px;
  margin-top: 0;
  overflow: scroll;
  overflow-x: hidden;
}
.c-scroll-view {
  width: 100%;
}
.c-scroll-bar {
  position: absolute;
  border-radius: 5px;
  z-index: 1;
  background: #70ad47;
}
/* 竖直滚动条 */
div.c-scroll-vertical-box {
  width: 10px;
  right: 2px;
}
div.c-scroll-horizontal-box {
  height: 10px;
}
</style>

 

domResize.js 如下:
import ResizeObserver from 'resize-observer-polyfill';

const listeners = (entries) => {
    for (let item of entries) {
        if (item.target && item.target.resizeListeners && item.target.resizeListeners.length) {
            for (let func of item.target.resizeListeners) {
                func(item);
            }
        }
    }
}

export const domResize = (ele, func) => {
    if (!ele.resizeListeners) {
        ele.resizeListeners = [];
        const myObserver = new ResizeObserver(listeners);
        myObserver.observe(ele);
    }
    ele.resizeListeners.push(func);
}

这里的domResize.js是element官方实现的,目的是为了监测一个容器大小发生变化,其实还在网上找到了另一种实现思路(也可以实现监听容器尺寸发生变化),代码如下:

/**
 * Created by taozh on 2017/5/6.
 * taozh1982@gmail.com
 */
var EleResize = {
  _handleResize: function (e) {
    var ele = e.target || e.srcElement;
    var trigger = ele.__resizeTrigger__;
    if (trigger) {
      var handlers = trigger.__z_resizeListeners;
      if (handlers) {
        var size = handlers.length;
        for (var i = 0; i < size; i++) {
          var h = handlers[i];
          var handler = h.handler;
          var context = h.context;
          handler.apply(context, [e]);
        }
      }
    }
  },
  _removeHandler: function (ele, handler, context) {
    var handlers = ele.__z_resizeListeners;
    if (handlers) {
      var size = handlers.length;
      for (var i = 0; i < size; i++) {
        var h = handlers[i];
        if (h.handler === handler && h.context === context) {
          handlers.splice(i, 1);
          return;
        }
      }
    }
  },
  _createResizeTrigger: function (ele) {
    var obj = document.createElement('object');
    obj.setAttribute('style',
      'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -1;');
    obj.onload = EleResize._handleObjectLoad;
    obj.type = 'text/html';
    ele.appendChild(obj);
    obj.data = 'about:blank';
    return obj;
  },
  _handleObjectLoad: function (evt) {
    this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
    this.contentDocument.defaultView.addEventListener('resize', EleResize._handleResize);
  }
};
if (document.attachEvent) {//ie9-10
  EleResize.on = function (ele, handler, context) {
    var handlers = ele.__z_resizeListeners;
    if (!handlers) {
      handlers = [];
      ele.__z_resizeListeners = handlers;
      ele.__resizeTrigger__ = ele;
      ele.attachEvent('onresize', EleResize._handleResize);
    }
    handlers.push({
      handler: handler,
      context: context
    });
  };
  EleResize.off = function (ele, handler, context) {
    var handlers = ele.__z_resizeListeners;
    if (handlers) {
      EleResize._removeHandler(ele, handler, context);
      if (handlers.length === 0) {
        ele.detachEvent('onresize', EleResize._handleResize);
        delete ele.__z_resizeListeners;
      }
    }
  }
} else {
  EleResize.on = function (ele, handler, context) {
    var handlers = ele.__z_resizeListeners;
    if (!handlers) {
      handlers = [];
      ele.__z_resizeListeners = handlers;

      if (getComputedStyle(ele, null).position === 'static') {
        ele.style.position = 'relative';
      }
      var obj = EleResize._createResizeTrigger(ele);
      ele.__resizeTrigger__ = obj;
      obj.__resizeElement__ = ele;
    }
    handlers.push({
      handler: handler,
      context: context
    });
  };
  EleResize.off = function (ele, handler, context) {
    var handlers = ele.__z_resizeListeners;
    if (handlers) {
      EleResize._removeHandler(ele, handler, context);
      if (handlers.length === 0) {
        var trigger = ele.__resizeTrigger__;
        if (trigger) {
          trigger.contentDocument.defaultView.removeEventListener('resize', EleResize._handleResize);
          ele.removeChild(trigger);
          delete ele.__resizeTrigger__;
        }
        delete ele.__z_resizeListeners;
      }
    }
  }
}
export default EleResize;

 

posted on 2018-10-25 15:22  cjs1992  阅读(4172)  评论(1编辑  收藏  举报