表格点击单元格,实现选中功能,并且实现复制选中单元格功能

一、背景

以elementui的table为基础实现,点击单元格实现单元格选中功能,按住ctrl、shift键实现选中效果,并且实现复制时如果单元格有选中的话,复制选中内容,否则实现复制当前被鼠标选中的内容,如果当前单元格是行编辑并且是第一次被打开,单元格的内容被选中

如情况一:

 

 

 情况二:

 

 

 二、实现过程

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', [])

 

 同时table的clickOut的事件也进行事件解绑

 

 

 

 



posted @ 2022-06-26 14:45  火烈鸟的梦  阅读(1565)  评论(0编辑  收藏  举报