参照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;

vue自定义滚动条的更多相关文章

  1. vue-gemini-scrollbar(vue组件-自定义滚动条)

    vue-gemini-scrollbar(vue组件-自定义滚动条) https://segmentfault.com/a/1190000013338560

  2. Vue.js 桌面端自定义滚动条组件|vue美化滚动条VScroll

    基于vue.js开发的小巧PC端自定义滚动条组件VScroll. 前段时间有给大家分享一个vue桌面端弹框组件,今天再分享最近开发的一个vue pc端自定义滚动条组件. vscroll 一款基于vue ...

  3. vue自定义可输入的选择框组件

    vue自定义可输入的选择框组件 props: 属性 说明 类型 默认值 selectDataList 下拉框中的内容 Array 空数组([]) value 输入框中的内容 String 空字符串(& ...

  4. uniapp以及微信小程序中scroll-view隐藏滚动条 自定义滚动条

    隐藏滚动条 1.全局隐藏滚动条,在app.vue中 ::-webkit-scrollbar{ display: none; } 2.局部隐藏藏滚动条 样式没有使用scoped属性时, 否则无效. .u ...

  5. CSS3自定义滚动条样式 -webkit-scrollbar(转)

    有没有觉得浏览器自带的原始滚动条很不美观,同时也有看到很多网站的自定义滚动条显得高端,就连chrome32.0开发板都抛弃了原始的滚动条,美观多了.那webkit浏览器是如何自定义滚动条的呢? 前言 ...

  6. vue自定义指令

    Vue自定义指令: Vue.directive('myDr', function (el, binding) { el.onclick =function(){ binding.value(); } ...

  7. jquery自定义滚动条 鼠标移入或滚轮时显示 鼠标离开或悬停超时时隐藏

    一.需求: 我需要做一个多媒体播放页面,左侧为播放列表,右侧为播放器.为了避免系统滚动条把列表和播放器隔断开,左侧列表的滚动条需要自定义,并且滚动停止和鼠标离开时要隐藏掉. 二.他山之石: 案例来自h ...

  8. 利用JS实现自定义滚动条

    一般默认的滚动条会比较丑,我们可以用简单的js实现自定义滚动条的功能: 代码如下: <!doctype html> <html> <head> <meta c ...

  9. javascript 学习之自定义滚动条加滚轮事件

    要自己写一个自定义滚动条加上滚轮事件,之前的没有滚轮事件不完整,今天整理了一个. 1.滚轮事件是不兼容的,firefox中是必需要用事件绑定的添加,用的DOMMouseScroll,当滚动鼠标的时候, ...

随机推荐

  1. Oracle两个数据库联合查询,使用Oracle DBLink

    创建dblink -- Create database link create shared database link COPYCITY_BZTOMY connect to db_A identif ...

  2. AND 初识

    框架

  3. oo第一次总结博客

    一. 多项式求导问题描述 基本概念的声明: 带符号整数 支持前导 0 的带符号整数,符号可忽略,如:+02.-16.19260817 等. 因子 变量因子 幂函数 一般形式 由自变量x和指数组成,指数 ...

  4. QTP测试.NET程序的时候,ComboBox下拉框控件选择后,运行时对象不可见解决方案

    解决方法: 录制时,选择下拉框数据的时候,不要鼠标单击选择,而是要用ENTER(回车键)来选择,才能完成选择,这样录制就OK了.

  5. 《深入理解java虚拟机》读书笔记——java内存区域和内存溢出异常

    几种内存溢出异常: 堆溢出 原因:创建过多对象,并且GC Roots到对象之间有可达路径. 分两种情况: Memory Leak:无用的对象没有消除引用,导致无用对象堆积.例如<Effictiv ...

  6. [PHP]正则表达式判断网址

    来源:https://segmentfault.com/q/1010000000584340/a-1020000000584362 Markdown 的作者之一写的正则表达式(原文在这) (?i)\b ...

  7. abaqus2016安装过程中出现error:unable to add abaqus command directory to PATH variable

    请问abaqus2016安装过程中出现error:unable to add abaqus command directory to PATH variable是什么原因,怎么解决啊,总是安装失败 这 ...

  8. linux xfs的一次io异常导致的crash

    returned. [ blocked seconds.----这个默认是120,该环境上是被人为设置1200 [8556407.425653] "echo 0 > /proc/sys ...

  9. anu小程序快速入门

    众所周知,微信推出小程序以来,可谓火遍大江南北,就像当前互联网兴起时,大家忙着抢域名与开私人博客一样.小程序之所以这么火,是因为微信拥有庞大的用户量,并且腾讯帮你搞定后台问题及众多功能问题(如分享,支 ...

  10. idea2018.1.5激活教程

    这是地址  链接: https://pan.baidu.com/s/1lx5AfMjADYFcQARi7_GNIw 密码: nvfi 1下载解压到任意目录(前提你能找到) 2将复制到 bin目录下 如 ...