需求:表格行数过多,就需要先滚动到表格底部,才能使用横向滚动条,这给用户带来了不便。
思路:在表格内部生成一个自定义横向滚动条,当表格原生的横向滚动条没出现在可视区域范围时,将自定义滚动条调整到视口底部位置,反之隐藏该自定义滚动条。
使用:由于用的是Vue,又涉及到操作Dom,故而把这个功能封装成一个指令,在el-table上添加指令即可。
过程:
main.js(定义全局指令)
//perfect-scrollbar插件的包
import ScrollBar from './direactives/scrollbar'
//对应的css
import 'perfect-scrollbar/css/perfect-scrollbar.css'
//全局指令
Vue.directive('fixed-scroll', ScrollBar)
scrollbar.js
//自定义滚动条
import PerfectScrollbar from 'perfect-scrollbar'
//对应的css
import 'perfect-scrollbar/css/perfect-scrollbar.css'
const updateScrollBar = el => {
const railX = el.querySelector('.ps__rail-x')
const _tbody = el //el为表格容器
// 如果table内部还有滚动条的话需要加上_tbody.scrollTop
// 视口的高度-tbody基于视口的top值-横向滚动条容器的高度
const _top = window.innerHeight - _tbody.getBoundingClientRect().top - railX.clientHeight
railX.style.top = `${_top}px`
railX.style.opacity = '1'
railX.style.display = 'block'
}
// 使用插件创建滚动条
const el_scrollBar = el => {
// 在元素上加点私活,名字随便取,确保不会和已有属性重复即可,取名叫做_ps_
if (el._ps_ instanceof PerfectScrollbar) {
el._ps_.update()
} else {
// el上挂一份属性
el._ps_ = new PerfectScrollbar(el, {
suppressScrollX: false,
suppressScrollY: true //y方向禁止
})
}
}
let isScrolling = false
let _scrollHander = null
let _resizeHander = null
// 自定义vue指令
const directive = {
// inserted(初次创建dom)获取使用自定义指令处的dom
inserted(el) {
el = el.querySelector('.el-table__body-wrapper')
if (!el) {
return console.warn('未发现className为el-table__body-wrapper的dom')
}
// 判断其样式是否存在position,并且position为"fixed","absolute",或"relative"
// 如果不符合条件,抛个错误,当然你也可以抛个警告顺便给其position自动加上"relative"
// 为什么要这样做呢,因为PrefectScrollbar实现原理就是dom注入两个div,一个是x轴一个是y轴,他们两的position都是absolute
//对css稍有常识的人都知道,absolute是相对于所有父节点里设置了position属性的最近的一个节点来定位的,为了能够正确定位,我们要给其设置position属性
const rules = ['fixed', 'absolute', 'relative']
if (!rules.includes(window.getComputedStyle(el, null).position)) {
console.error(`perfect-scrollbar所在的容器的position属性必须是以下之一:${rules.join('、')}`)
}
// el上挂一份属性
el_scrollBar(el)
updateScrollBar(el)
//注册scroll和resize事件
_scrollHander = () => {
if (!isScrolling) {
window.requestAnimationFrame(() => {
updateScrollBar(el)
isScrolling = false
})
}
isScrolling = true
}
_resizeHander = () => {
updateScrollBar(el)
}
document.addEventListener('scroll', _scrollHander)
window.addEventListener('resize', _resizeHander)
},
// 更新don的时候
componentUpdated(el, binding, vnode) {
const { expression } = binding
el = el.querySelector('.el-table__body-wrapper')
if (!el) {
return console.warn('未发现className为el-table__body-wrapper的dom')
}
const handler = () => vnode.context[expression].apply()
// vnode.context其实就是vue实例,这里其实无需实例也直接用vue的静态方法
vnode.context.$nextTick(() => {
try {
el_scrollBar(el)
updateScrollBar(el)
if (expression) {
handler()
}
} catch (error) {
console.error(error)
}
})
},
unbind() {
document.removeEventListener('scroll', _scrollHander)
window.removeEventListener('resize', _resizeHander)
}
}
export default directive
组件中使用
<el-table :data="deliverTable" border highlight-current-row :header-cell-style="{ background: '#eef1f6', color: '#606266' }" v-loading="listLoading" v-fixed-scroll>
注意:如果表格有固定列,需要给横向滚动条设置高于固定列的层级z-index
App.vue
.ps__rail-x {
display: block;
z-index: 999;
}
实现:当表格底部不在可视区域范围内时,横向滚动条固定在视口底部的位置。
参考:vue中使用perfect-scrollbar
本文转载自: https://blog.csdn.net/qq_56162766/article/details/130240104
版权归原作者 能当饭吃么你说_ 所有, 如有侵权,请联系我们删除。
版权归原作者 能当饭吃么你说_ 所有, 如有侵权,请联系我们删除。