表格点击单元格,实现选中功能,并且实现复制选中单元格功能
一、背景
以elementui的table为基础实现,点击单元格实现单元格选中功能,按住ctrl、shift键实现选中效果,并且实现复制时如果单元格有选中的话,复制选中内容,否则实现复制当前被鼠标选中的内容,如果当前单元格是行编辑并且是第一次被打开,单元格的内容被选中
如情况一:
情况二:
![](https://img2022.cnblogs.com/blog/2476357/202206/2476357-20220626141519517-19081788.png)
二、实现过程
1、element提供了cellClick事件,里面有row,column,cell,event的参数,其中row里面有对应的rowKey属性,column里面有id属性,并且每行的rowkey不同,每列的id不同,通过rowClass属性可以将rowKey作为没行的样式,而每列都有id属性为class
2、可以根据tbody里面的tr,td和rowKey和id拿到对应的class,因此可以找到选中的元素,实现选中样式
3、实现选中项复制的功能,使用的是插件vue-clipboard2,当然也可以使用document.execCommand('Copy') 方法
4、获取选中的内容,如果是单元格内容,则是将选中内容的值进行拼接,否则直接取用window.getSelection().toString()
1)选中值拼接需要注意的点是,里面是直接是文本,比如`<div>你好</div>`,还是`<input value="世界">`,有特殊情况是里面有多个input所以要搞明白文本绑定在那个上面了
2)如果行编辑组件里面的放大镜组件,会造成点击放大镜组件弹窗出来后,再点击弹窗里面的table,这个时候window.getSelection().toString()还是有值,没有被清除,所以此时可能有问题,因此如果不是行编辑的情况下需要先清除选中项
var range = document.createRange() range.selectNodeContents(document.createElement('div')) document.getSelection().removeAllRanges() document.getSelection().addRange(range)
注意:不能直接用document.getSelection().removeAllRanges(),因为涉及到光标位置,所以如果直接删除的话,每次光标位置都会归为0,因此不能直接用这个方法
同时注意考虑只有在不是行编辑的情况下才能进行
5、实现如果单元格是行编辑则选中单元格内的内容功能
const input = this.getInputElm(cell) if (input) { input.select() input.focus() } else { var range = document.createRange() range.selectNodeContents(cell) document.getSelection().removeAllRanges() document.getSelection().addRange(range) }
6、实现复制功能,利用的是document的keydown事件监听,如果event.ctrlKey & event.keyCode === 67,则实现复制
需要注意的是,keydown的事件需要绑定在document上,绑定在table元素上,会出现事件监听失效,可能是行编辑的情况,还有就是绑定数据的this可能不一样,因此在绑定事件的时候最好使用bind方法将this绑定,并且在绑定事件之前进行事件解绑
绑定事件:
// 实现单元格复制的事件 const fun = this.documentCopy.bind(this) const tableKeyDownFunList = this.$utils.deepClone(this.tableKeyDownFunList) tableKeyDownFunList.push({ scope: this, fun: fun }) document.addEventListener("keydown", fun) // this.$refs.table?.$el.addEventListener("keydown", fun) this.$store.commit('SET_TABLE_KEY_DOWN_FUN_LIST', tableKeyDownFunList)
解绑事件:
this.tableKeyDownFunList.forEach((item, index) => { document.removeEventListener('keydown', item.fun) // this.$refs.table?.$el.removeEventListener('keydown', item.fun) }) this.$store.commit('SET_TABLE_KEY_DOWN_FUN_LIST', [])