ScalaJS 上的可拖动 removeEventListener 不起作用

draggable on ScalaJS removeEventListener does not work

基于该 js 演示:http://jsfiddle.net/wfbY8/737/

class Draggable(element: HTMLDivElement) {

  var offX: Double = 0
  var offY: Double = 0

  val divMove = (e:MouseEvent) => {
    //element.style.position = 'absolute';
    element.style.top = (e.clientY-offY) + "px"
    element.style.left = (e.clientX-offX) + "px"
  }

  val mouseDown = (e:MouseEvent) => {
    offY = e.clientY - element.offsetTop
    offX = e.clientX - element.offsetLeft
    window.addEventListener("mousemove", divMove, useCapture = true)
    println("added")
  }

  val mouseUp = (e:MouseEvent) => {
    window.removeEventListener("mousemove", divMove, useCapture = true)
     println("removed")
  }

  def addListeners(){
    element.addEventListener("mousedown", mouseDown, useCapture = false)
    window.addEventListener("mouseup", mouseUp, useCapture = false)

  }

  addListeners()

}

从客户端代码我使用它是这样的:

  val panelElem = document.getElementById(COMPONENT_ID).asInstanceOf[HTMLDivElement]
  if (draggable == null) {
    draggable = new Draggable(panelElem)
  }

我在日志中看到 "added" 和 "removed"。但是元素仍然可以移动(当我移动鼠标而不按下它时)对我来说就好像我没有从侦听器(在 mouseUp 上)删除 mousemove 事件一样。

不知道为什么..

发生这种情况是因为您有效地将 Scala 函数(lambda)分别转换为 addremove 的 JS 函数。在 Scala.js 中,Scala 函数会根据需要隐式 转换 为 JS 函数。但是,每次转换都会产生不同的 JS 函数(它没有相同的 identity)。因此,您要删除的功能与您添加的功能不同,当然这没有任何效果。

您可以通过强制提前进行转换来解决此问题,这样您就可以添加和删除相同的函数。为此,只需将显式类型添加到您的函数 vals 作为 JS 函数:

  val divMove: js.Function1[MouseEvent, Unit] = (e:MouseEvent) => {
    ...
  }

这样,从 Scala 函数到 JS 函数的转换只发生一次,并且是给 add- 和 removeEventListener.

的同一个 JS 函数