+-
调用Delete键删除jsplumb流程的线条或节点

前段时间做了一个前端流程设计器,基于jsplumb,可拖拽。大领导看了表示很满意,同时提出一个建议,线条删除不符合大众习惯,一般人猜不到(我做的是双击线条来删除),能否支持选中线条后敲击键盘Delete键来删除线条,我一口答应,结果发现踩到了坑。

首先,我接到这个小需求后,第一反应是很简单嘛,我只要拿到线条对象,然后给其绑定keydown事件,接着在函数体内判断keyCode后,再调用jsplumb的删除线条事件就好了。

思路很简单,但是在实际上自己做的时候,遇到了很多小细节的问题,导致无法触发事件,接下来我们来看一下我遇到了哪些问题。

接到领导需求后,我立马就花了两分钟时间写了这么一段代码:

this.jsPlumb.bind('keydown', (conn, originalEvent) => {
  let event = originalEvent || window.event
  if (event.keyCode === 46) {
    this.$confirm('确定删除所点击的线吗?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        this.jsPlumb.deleteConnection(conn)
        console.log(originalEvent)
      })
      .catch(() => {})
  }
})

但是当我运行的时候,发现无论如何也没办法触发这个事件。

后来才发现,需要用document.addEventListener('keydown',function(){})才能实现触发,于是很快第二版的代码出来了:

    alert('试试看能否触发')
    let event = originalEventConn || window.event
    if (event.keyCode === 46) {
      this.$confirm('确定删除所点击的线吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.jsPlumb.deleteConnection(conn)
        })
        .catch(() => {})
    }
  })

执行的时候,事件成功触发,但是无论如何也删不掉线条,问题在哪儿呢。经过排查,删除线条的方法deleteConnection本身没问题,问题出在删除的conn对象了。

众所周知,在调用Delete时,我们需要先点击一下线条来选中它,然后才能再敲击键盘来删除,那么这个对象需要在点击线条的时候就拿到,所以,我们定义一个全局变量selectedLine,在这块给它赋值:

  // 给选中的线条赋值
  this.selectedLine = conn
  // 点击线条后取出当前线条的id - 和右侧条件表单相互匹配(一个线条对应一个不同的表单内容)
  this.currentLineId = conn.sourceId + '-' + conn.targetId
  ...
  ...
  ...
})

然后,我写出了第三版,并对一些小细节做了优化:

「用keyup取代kedown」:keydown事件如果点击一次没影响,但如果一直按住一个键不松开的时候,事件就会一直触发,反复调用方法,这样无疑就会造成性能的损耗;而keyup只会在松开键盘的一瞬间触发,并且只会触发一次。 「加入Backspace键删除」:在日常使用习惯中,除了用Delete键删除,我们还习惯于用Backspace键来进行回删,所以基于用户体验性,我将Backspace的keyCode也加入了判断,这样用户敲击两个就按中的任意一个,都可以方便的删除线条。

代码如下:

document.addEventListener('keyup', (conn, originalEventConn) => {
  let event = originalEventConn || window.event
  // 8--backspace, 46--delete
  if (event.keyCode === 8 || event.keyCode === 46) {
    this.$confirm('确定删除所点击的线吗?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        this.jsPlumb.deleteConnection(this.selectedLine)
      })
      .catch(() => {})
  }
})

到这里,这个小需求、或者说是功能优化就做完了,为了怕后续遗忘,特此记录,也可以和遇到此类问题的伙伴们分享。

关于作者:JeremyCC

一个爱唱歌的前端工程狮,喜欢我可以点关注噢!(头像仅供参考,哈哈)