效果如图:
原始版本代码
<template>
<div>
<el-table
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
@select="pinSelect"
ref="multipleTable"
>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="日期" width="120">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column prop="name" label="姓名" width="120"></el-table-column>
<el-table-column prop="address" label="地址" show-overflow-tooltip></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: 'ElementTable',
data() {
return {
origin: -1, // 这里给一个变量作为起点
pin: false, // 这里给一个变量,默认为false,不按住
tableData: [
{
date: '2016-05-01',
name: '王幼虎',
address: '上海市普陀区金沙江路 1511 弄'
},
{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1512 弄'
},
{
date: '2016-05-03',
name: '王中虎',
address: '上海市普陀区金沙江路 1513 弄'
},
{
date: '2016-05-04',
name: '王老虎',
address: '上海市普陀区金沙江路 1514 弄'
},
{
date: '2016-05-05',
name: '王死虎',
address: '上海市普陀区金沙江路 1515 弄'
},
{
date: '2016-05-06',
name: '王骨虎',
address: '上海市普陀区金沙江路 1516 弄'
},
{
date: '2016-05-07',
name: '王灰虎',
address: '上海市普陀区金沙江路 1517 弄'
}
],
multipleSelection: [],
selected: false,
lists: []
}
},
watch: {
lists(val) {
console.log('选中的数据', val)
}
},
methods: {
handleSelectionChange(val) {
this.multipleSelection = val
// console.log('选中数据', this.multipleSelection)
},
pinSelect(item, row) {
let selected = item.length && item.indexOf(row) !== -1
this.selected = selected
const data = this.$refs.multipleTable.tableData
const origin = this.origin
const endIdx = row.index
if (this.selected) {
if (this.pin && item.includes(data[origin])) {
const sum = Math.abs(origin - endIdx) + 1
const min = Math.min(origin, endIdx)
let i = 0
while (i < sum) {
const index = min + i
this.$refs.multipleTable.toggleRowSelection(data[index], true)
i++
const isIndexExists = this.lists.some(item => item.index === index)
if (!isIndexExists) {
this.lists.push(data[index])
}
}
} else {
this.origin = row.index
this.lists = item
}
} else {
if (!this.pin && !item.includes(data[origin])) {
const sum = Math.abs(origin - endIdx) + 1
const min = Math.min(origin, endIdx)
let i = 0
while (i < sum) {
const index = min + i
this.$refs.multipleTable.toggleRowSelection(data[index], false)
i++
this.lists = this.lists.filter(item => item.index !== index)
}
} else {
this.origin = row.index
this.lists = item
}
}
}
},
// 这里是获取键盘事件
mounted() {
window.addEventListener('keydown', code => {
if (code.keyCode === 16 && code.shiftKey) {
if (this.selected) {
this.pin = true
} else {
this.pin = false
}
}
})
window.addEventListener('keyup', code => {
if (code.keyCode === 16) {
if (this.selected) {
this.pin = false
} else {
this.pin = true
}
}
})
},
created() {
this.tableData.forEach((item, index) => {
// 遍历索引,赋值给data数据
item.index = index
})
}
}
</script>
<style scoped></style>
以上写法问题:
1、使用shift连选会导致@selection-change选中数据不对
当你按住 Shift 键连选多行时,如果手动调用了 toggleRowSelection 来选中多行,会导致 @selection-change 事件触发多次,因此 @selection-change 中的选中数据可能不准确。
可以使用 @select-all 和 @select 事件,结合手动管理选中行状态。
我这里通过属性selectionChangeAllowed: true, // 控制 @selection-change 触发
2、各种连选,取消反选的bug ex:从1连选到10,再从10取消连选到2,点2再点8,不按住shift也会从2连选到8;点击全选,再点击3会出现1到3连选取消;从1连选到10,单选取消4是单个取消,再点8,会连选取消到8。
解决以上bug的完整代码如下:
<template>
<div>
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
@select="pinSelect"
>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="日期" width="120">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column prop="name" label="姓名" width="120"></el-table-column>
<el-table-column prop="address" label="地址" show-overflow-tooltip></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: 'ElementTable',
data() {
return {
origin: -1, // 这里给一个变量作为起点
pin: false, // 这里给一个变量,默认为false,不按住
tableData: [
{
date: '2016-05-01',
name: '王幼虎',
address: '上海市普陀区金沙江路 1511 弄'
},
{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1512 弄'
},
{
date: '2016-05-03',
name: '王中虎',
address: '上海市普陀区金沙江路 1513 弄'
},
{
date: '2016-05-04',
name: '王老虎',
address: '上海市普陀区金沙江路 1514 弄'
},
{
date: '2016-05-05',
name: '王死虎',
address: '上海市普陀区金沙江路 1515 弄'
},
{
date: '2016-05-06',
name: '王骨虎',
address: '上海市普陀区金沙江路 1516 弄'
},
{
date: '2016-05-07',
name: '王灰虎',
address: '上海市普陀区金沙江路 1517 弄'
}
],
multipleSelection: [],
selected: false,
lists: [],
selectionChangeAllowed: true // 控制 @selection-change 触发
}
},
watch: {
lists(val) {
console.log('选中的数据', val)
}
},
methods: {
handleSelectionChange(val) {
if (this.selectionChangeAllowed) {
this.multipleSelection = val
// console.log('选中数据', this.multipleSelection)
}
},
// 这里是select事件开始
pinSelect(item, row) {
let selected = item.length && item.indexOf(row) !== -1
this.selected = selected // 取消还是选中
const data = this.$refs['multipleTable'].tableData
const origin = this.origin
const endIdx = row.index
if (this.selected) {
// 是否按shift的
if (this.pin && item.includes(data[origin])) {
// 当按住shift 进行连选时,暂时禁用 @selection-change 事件触发
this.selectionChangeAllowed = false
const sum = Math.abs(origin - endIdx) + 1
const min = Math.min(origin, endIdx)
let i = 0
while (i < sum) {
const index = min + i
this.$refs['multipleTable'].toggleRowSelection(data[index], true)
i++
// console.log('返回', data[index])
// 检查 arr 数组中是否存在相同 index 的元素
const isIndexExists = this.lists.some(item => item.index === index)
if (!isIndexExists) {
this.lists.push(data[index])
} else {
console.log('index 已存在,不添加', data[index])
}
}
// 连选操作结束,手动更新
this.$nextTick(() => {
this.selectionChangeAllowed = true
this.rollSelectionChange(this.lists)
})
} else {
this.origin = row.index
this.lists = item
}
} else {
// console.log('取消选中')
// 是否按shift
if (this.pin && !item.includes(data[origin])) {
this.selectionChangeAllowed = false
const sum = Math.abs(origin - endIdx) + 1
const min = Math.min(origin, endIdx)
let i = 0
while (i < sum) {
const index = min + i
this.$refs['multipleTable'].toggleRowSelection(data[index], false)
i++
// 使用 filter 删除匹配的元素
this.lists = this.lists.filter(item => item.index !== index)
}
// 连选操作结束,手动更新 selectedRows
this.$nextTick(() => {
this.selectionChangeAllowed = true // 恢复 @selection-change 事件
this.rollSelectionChange(this.lists)
})
} else {
this.origin = row.index
this.lists = item
}
}
}
},
// 这里是获取键盘事件
mounted() {
window.addEventListener('keydown', code => {
if (code.keyCode === 16 && code.shiftKey) {
this.pin = true
} else {
this.pin = false
}
})
window.addEventListener('keyup', code => {
if (code.keyCode === 16 && code.shiftKey) {
this.pin = true
} else {
this.pin = false
}
})
},
created() {
this.tableData.forEach((item, index) => {
// 遍历索引,赋值给data数据
item.index = index
})
}
}
</script>
<style scoped></style>
本文是基于参考文章写的,如果对你有帮助,留下小心心~