参照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. Postman 设置全局变量和环境变量设置(之 图形界面设置变量)

    在Postman中有两种方法添加变量:1.图形界面操作添加   2.执行代码添加 1.图形界面操作添加,点击右上角齿轮按钮手动添加所需测试环境:   2.点击右上角的小眼睛可以编辑.添加“全局变量”和 ...

  2. [论文阅读]MobileNetV2: Inverted Residuals and Linear Bottlenecks

    0.      本文贡献点 本文的主要贡献点是一个构造了一个结构,称为the inverted residual with linear bottleneck.该结构与传统的residual bloc ...

  3. webpy学(ban)习(砖)记录

    参考链接:http://blog.csdn.net/caleng/article/details/5712850 参考代码:http://files.cnblogs.com/files/tacyeh/ ...

  4. 72.纯 CSS 创作气泡填色的按钮特效

    原文地址:https://segmentfault.com/a/1190000015560736 感想:过渡效果+xyz中一轴. HTML code: <nav> <ul> & ...

  5. loadrunner-参数化

    参数化的目的: 1.数据库或应用程序对提交请求里的参数值进行唯一性校验 2.为了避免查询缓存导致的性能测试结果失真 (语法检查-语意检查-检查缓存(有直接从数据库给)没有就生成执行计划-按照执行计划去 ...

  6. Spring @Autowired注解在非Controller中注入为null

    问题描述 今天在写一个工具类,里面用了@Autowired注入了StringRedisTemplate以及RedisTemplate时,在template.opsForValue().set(key, ...

  7. cdh启动datanode报错

    问题: 为cdh新增节点时,在分配datanode后,启动报错 Can't open /iot/opt/cloudera-manager/cm-5.11.2/run/cloudera-scm-agen ...

  8. springboot的打包方式

    先写一个测试接口 package com.example.demo; import org.springframework.web.bind.annotation.RequestMapping; im ...

  9. js数值大小判断的错误

    1.js中定义一个变量i,判断i的取值在[1,3]中的错误写法 if(1<= i <= 3) 假设js的值为4,浏览器在解析js时会先将1与4比较 ,显然1<= 4,返回结果为1,然 ...

  10. docker镜像无法下载或者下载缓慢

    解决docker镜像无法下载的问题 2015年10月02日 16:01:05 阅读数:20776 克服跨洋网络延迟,使用Docker Hub Mirror加速Docker官方镜像下载 http://c ...