el-table上下键高亮当前行

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 = 行高 * 倍数就可以了

上一篇:前端模糊查询


下一篇:vue+element使用sortable拖拽实现行排序