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