借助elementUI的table组件开发表格多选功能组件。
需要考虑的问题:
- 监听按键,如shift键,keyCode = 16。考虑elementUI的选择事件是否返回了鼠标键盘操作的事件,没有的话只能自己监听,并销毁。
- 不影响原有elementUI的功能属性使用。使用listeners。
- 考虑表格从上至下选择,从下至上选择。
- template部分
<template>
<el-table
ref="mainTable"
:data="tableData"
v-bind="$attrs"
v-on="$listeners"
@selection-change="handleSelectChange"
@select="handleSelectionChange"
@select-all="handleSelectionChange"
>
<slot />
</el-table>
</template>
- js部分
接收外部传入的data数据,循环为每一条数据加上唯一的有序标记_index
。
props: {
data: {
type: Array,
required: true
}
},
watch: {
data(val) {
this.addAttrIndex(val)
}
},
addAttrIndex(list) {
if (list.length) {
for (let i = 0; i < list.length; i++) {
Object.defineProperty(list[i], '_index', { // 添加index属性 用于shift多选
value: i,
writable: true,
enumerable: false
})
}
}
this.tableData = list
}
监听键盘事件并及时销毁。
mounted() {
addEventListener('keydown', this.keyDown, false)
addEventListener('keyup', this.keyUp, false)
},
beforeDestroy() {
removeEventListener('keydown', this.keyDown)
removeEventListener('keyup', this.keyUp)
},
keyDown({ keyCode }) { if (keyCode === 16) { this.shiftDown = true } },
keyUp({ keyCode }) { if (keyCode === 16) { this.shiftDown = false } },
重新定义选择的事件,包括@selection-change
@select
@select-all
。
- 选择数据改变事件
@selection-change
handleSelectChange(selection) {
this.selection = selection
this.$emit('selection-change', selection)
}
- 选择某行数据事件及全部选择事件
@select
及@select-all
handleSelectionChange(val, row) {
const { shiftDown, preClickIndex } = this
const checked = val.includes(row)
// 选中+shift键+preClickIndex存在
if (checked && shiftDown && preClickIndex > -1) {
val = this.shiftMultiSel(preClickIndex, row._index)
this.$nextTick(() => {
for (let i = 0; i < val.length; i++) {
this.$refs.mainTable.toggleRowSelection(val[i], true)
}
})
}
// 没有按shift时 记录位置
this.preClickIndex = (row && checked && !shiftDown) ? row._index : -1
this.$emit('select', val, row)
},
shiftMultiSel(preIndex, rowIndex) { // shift多选 返回应该选择rows
const { tableData } = this
const top = Math.min(preIndex, rowIndex)
const bottom = Math.max(preIndex, rowIndex)
return Array.from(new Set([...this.selection,
...(tableData.slice(top, bottom + 1))]))
}
大概思路就是这样,代码还是比较简单的!