前言
脱离element-ui又借鉴element-ui,实现类似el-table的固定列和表头的效果
- 1-1固定,1-2只支持上下滑动,2-1只支持左右滑动,2-2上下、左右均可滑动
- 其中下图中1-2和2-1两part的滑动事件应用了el-table的mousewheel
效果
实现
布局
:
<div class="tree_table" v-on="handleBodyScroll, resize: handleBodyScroll }">
<!-- 右侧活动区(2-1、2-2) -->
<div class="scroll_table" ref="tableScroll">
<!-- 2-1 -->
<div class="header" ref="scrollHead" v-mousewheel="handleHeaderMousewheel">
<ul class="header_row row" :style="{ 'width': ulBoxWidth }">
<li v-for="(date, index) in dateTitList" :key="'head' + index">
{{ date.dateText }}
</li>
</ul>
</div>
<!-- 2-2 -->
<div class="body" ref="tableContent">
<ul v-for="(item, index) in list" :key="index" class="row" :style="{ 'width': ulBoxWidth }" @mouseenter="handleMouseEnter(index)" @mouseleave="handleMouseLeave(index)">
<li v-for="(date, index) in dateTitList" :key="'body' + index" class="border-dash">
<span>1</span>
</li>
</ul>
</div>
</div>
<!-- 左侧固定区(1-1、1-2) -->
<div class="fixed_table" :class="{'table-fixed-left-scroll': hasLeft}">
<!-- 1-1 -->
<div class="fixed_header">
<ul class="header_row row">
<li>项目</li>
</ul>
</div>
<!-- 1-2 -->
<div class="fixed_cont" ref="fixedBody" v-mousewheel="handleFixedMousewheel">
<ul v-for="(item, index) in list" :key="'fixed_item' + index" class="row" @mouseenter="handleMouseEnter(index)" @mouseleave="handleMouseLeave(index)">
<li class="border-dash">{{ item.title }}</li>
</ul>
</div>
</div>
</div>
主要方法
:
// 滚动右侧body区触发
handleBodyScroll(event) {
this.scrollValue = this.bodyWrapper.scrollLeft
this.hasLeft = this.scrollValue > 0
this.$refs.fixedBody.scrollTop = this.bodyWrapper.scrollTop
this.$refs.scrollHead.scrollLeft = this.scrollValue
},
// 滚动左侧固定列触发
handleFixedMousewheel(event, data) {
const bodyWrapper = this.bodyWrapper
if (Math.abs(data.spinY) > 0) {
const currentScrollTop = this.bodyWrapper.scrollTop
if (data.pixelY < 0 && currentScrollTop !== 0) {
event.preventDefault()
}
if (data.pixelY > 0 && bodyWrapper.scrollHeight - bodyWrapper.clientHeight > currentScrollTop) {
event.preventDefault()
}
bodyWrapper.scrollTop += Math.ceil(data.pixelY / 5)
} else {
bodyWrapper.scrollLeft += Math.ceil(data.pixelX / 5)
}
},
// 滚动头部日期组触发
handleHeaderMousewheel(event, data) {
const { pixelX, pixelY } = data;
if (Math.abs(pixelX) >= Math.abs(pixelY)) {
event.preventDefault();
this.bodyWrapper.scrollLeft += data.pixelX / 5;
}
}
element-ui的mousewheel
import normalizeWheel from 'normalize-wheel'
const isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
const mousewheel = function(element, callback) {
if (element && element.addEventListener) {
element.addEventListener(isFirefox ? 'DOMMouseScroll' : 'mousewheel', function(event) {
const normalized = normalizeWheel(event);
callback && callback.apply(this, [event, normalized]);
});
}
};
export default {
bind(el, binding) {
mousewheel(el, binding.value);
}
};