el-table上下键高亮当前行
数据值定义
data () {
return {
// 表格跳过的行高
skipRowHeight: {},
// 超出视口高的索引
overViewIndexArr:[],
// 当前行索引
currentchangeData:0,
// 表格数据
tableData:[]
}
}
添加键盘监听
activated () {
document.addEventListener('keydown', this.keys)
},
deactivated () {
document.removeEventListener('keydown', this.keys)
},
事件函数
keys (e) {
if (e.keyCode === 38) {
if (this.currentchangeData && this.currentchangeData > 0) {
this.handleDicKeyDownFocusCurrentRow('up', e)
}
} else if (e.keyCode === 40) {
if (this.currentchangeData < this.tableData.length - 1) {
this.handleDicKeyDownFocusCurrentRow('down', e)
}
}
}
处理dom元素及调用
handleDom () {
const tableBodyEl = this.$refs.table.$el.querySelector('.el-table__body')
const allTableRowEl = tableBodyEl.querySelectorAll('.el-table__row')
let calcRowHeight = 0
allTableRowEl.forEach((item, index) => {
if (Number(calcRowHeight) >= Number(tableContentHeight)) {
this.overViewIndexArr.push(index)
}
calcRowHeight += item.offsetHeight
this.$set(this.skipRowHeight, index, item.offsetHeight)
})
}
/**
需要给表格加上当前行改变事件
<el-table @current-change="currentchange"></el-table>
*/
// 当前行
currentchange (val) {
if (val) {
for (let i = 0; i < this.tableData.length; i++) {
if (this.tableData[i].id === val.id) {
this.currentchangeData = i
}
}
}
},
// 你的查询数据函数
handleSeach () {
...
this.tableData = res
// 这里需要使用nextTick,我们需要的dom需要立马在数据赋值后更新
this.$nextTick(() => {
this.overViewIndexArr = []
this.handleDom()
})
}
函数主体
handleDicKeyDownFocusCurrentRow (direction, e) {
const tableContentHeight = this.$refs.table.bodyWrapper.offsetHeight
// 可视区域内允许最大行数
let maxRowInView = (Math.min(this.overViewIndexArr) || 0) - 2
const currentRowIndex = (this.currentchangeData || 0)
const calcMulti = direction === 'down' ? 1 : -1
// 特殊处理超出可视高才开始进行滚动
const needScroll = (currentRowIndex - maxRowInView) >= 0
const currentRowOffetHeight = document.querySelector('.el-table__row.current-row').offsetHeight
this.$nextTick(() => {
// 越界判断
if (this.currentChangeData === 0 && direction === 'up') return
if (this.currentChangeData === this.tableData.length && direction === 'down') return
e.preventDefault()
if (needScroll) {
const skipHeight = Object.values(this.skipRowHeight).slice(0, currentRowIndex + 1).reduce((pre, cur) => pre + cur, 0)
let beyondViewHeight = skipHeight - tableContentHeight
// 特殊处理不确定的行高,不需要的话直接替换成 行高 * 上下倍数即可
// 这里的倍数就是你想一次按键滚动几个单元格的距离
const moveHeight = direction === 'down' ? (currentRowOffetHeight * calcMulti * 2) : (this.skipRowHeight[currentRowIndex - 1] * calcMulti)
setTimeout(() => {
this.$refs.table.bodyWrapper.scrollTop = (beyondViewHeight + moveHeight)
}, 0)
}
})
this.$refs.table.setCurrentRow(this.tableData[currentRowIndex + calcMulti])
},
整体思路:
-
获取表格的可视高度
-
动态获取每一行的高度
我这里是因为特殊需求决定,不能添加
show-overflow-tooltip
并且不能出现横向滚动条,某列会出现换行如果是确定固定行高的情况下,可以省去上面获取dom的操作,直接定义行高
-
当鼠标点击某行时,记录索引。算出索引之前加起来的高度(
skipHeight
)然后在减去表格视口高度(tableContentHeight
) -
然后根据表格上下键来进行操作,将超出视口高(
beyondViewHeight
)加上滚动距离即可 -
最后达到的效果就是高亮行一定会处于表格可视区域内的最下方(如果想完美调整到最后一行,直接调试
maxRowInView
的数值就行)如果你只是想单纯实现上下而已,可以直接暴力的
this.$refs.table.bodyWrapper.scrollTop = 行高 * 倍数
就可以了