参照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. sublimetext 创建一个php命令行编译环境

    菜单栏=>工具->编译系统=>新编译系统(插入如下代码,前提是有php批处理 然后编译php ctrl+b即可) { "cmd": ["php" ...

  2. Python数据类型的内置函数之list(列表)

    Python数据类型内置函数 - str(字符串) - list(列表) - tuple(元组) - dict(字典) - set(收集) list(列表)的操作 - (append)在列表最后追加指 ...

  3. kubenetes服务发现

    一.基于 iptables 的 Service 实现 Pod的ip地址不是固定了.Service通过selector属性和后端Pod关联,被selector选中的Pod被称为Service的Endpo ...

  4. 201772020113 李清华《面向对象程序设计(java)》第17周学习总结

    1.实验目的与要求 (1) 掌握线程同步的概念及实现技术: (2) 线程综合编程练习 2.实验内容和步骤 实验1:测试程序并进行代码注释. 测试程序1: l  在Elipse环境下调试教材651页程序 ...

  5. Linux部署笔记分享

    # Linux部署 ## 安装lrzsz1. 安装lrzsz: yum -y install lrzsz2. 进入tmp目录3. rz 上传安装文件 jdk-8u65-linux-x64.tar.gz ...

  6. 服务器硬盘--SAS盘和SATA盘

    一.SAS和SATA SATA: Serial Advanced Technology Attachment,又叫串口硬盘,是将主机总线适配器连接到硬盘的总线接口. SAS: Serial Attac ...

  7. join,left join,inner join,full join的区别?

    left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录inner join(等值连接) 只 ...

  8. RocketMQ入门(生产者)_2

    从 RocketMQ环境搭建_1 我们已经建立了MQ的Server,接下来就是简单的生产和消费的过程. 1. rocketMQ的源码中有个示例代码example  ,我们从Apache官网中可以下载源 ...

  9. PeopleSoft查看所有translate value

    下面sql可以列出PS中所有translate value SELECT FIELDNAME, FIELDVALUE, EFFDT, EFF_STATUS, XLATLONGNAME, XLATSHO ...

  10. 关于ASP.NET 服务器报错 Server Error in '/' Application Runtime Error 错误及解决方法

    今天遇到一个错误 程序在服务器上运行时报错 先贴上错误代码 自己也在网上找了一些解决方法,把错误定位到服务器的配置文件也就是Web.config的问题, 于是在system.web节点下 加上cust ...