当使用带有函数参数的.bind()时,事件不会在mousedown上更新

时间:2017-12-01 14:50:50

标签: javascript javascript-events mouseevent prototype bind

我正在尝试在没有jquery的情况下重写jquery插件,我无法弄清楚为什么当我使用.bind()时事件不会在函数中更新参数。我已将问题简化为以下内容:



function IMdraw(div) {
	this.div = div
	this.div.addEventListener('mousedown', this.mousedown.bind(this));
}

IMdraw.prototype = {

	onMouseMove: function (fn) {
		this.moveHandler = fn;
		this.div.addEventListener('mousemove', this.moveHandler, false);
	},
	
	move1: function(e, arg) {
		console.log('move1')
		console.log(e.offsetX);
        console.log(e.offsetY);
	},

	move2: function(e) {
      console.log('move2')
	  console.log(e.offsetX);
      console.log(e.offsetY);
	},


	mousedown: function(e) {
      var arg = 3;
      this.onMouseMove(this.move1.bind(this));
      this.onMouseMove(this.move2.bind(this, e, arg));

	},

}

var obj = new IMdraw(document.querySelector('div'));

<div style="width:500px; height:500px; background: blue;">
  </div>
&#13;
&#13;
&#13;

正如您在单击蓝色div并在div中移动光标时所看到的那样,在move2函数中,offsetX和offsetY不会更新,但会在move1函数中更新。

有没有解释为什么它会这样?我相信我正在使用.bind()。

1 个答案:

答案 0 :(得分:0)

问题是您的bind调用干扰了事件对象到事件回调函数的自动传递。

  • 使用move1,您没有传递任何内容,因此e正确指向 自动传递给事件的mousemove事件 回调函数。 arg未通过arg,因此move1undefined}内部将为move2
  • 使用e,您通过传递自己的参数来干扰事件对象的自动传递。您是mousedown参数 传递是来自mousemove事件的事件对象,而不是arg事件 在move2发生时更新,因此您始终可以看到点击鼠标时的偏移量。您确实已将arg传递给fun.bind(thisArg[, arg1[, arg2[, ...]]]),并且可以使用。

解决方案是根本不传递事件对象,让它像往常一样自动传递,只传递你需要的任何额外数据(在你的情况下为addEventListener),但是参数您通过的将是该案件在此案件中收到的第一批案件,该事件将是最后一天(与通常情况相反)。

FROM MDN

  

语法 onmousemove

     

<强>参数

     

<强> thisArg

     

作为this参数传递给目标函数的值   当调用绑定函数时。如果绑定,则忽略该值   函数是使用new运算符构造的。

     

arg1,arg2,...

     

prepend 的参数提供给绑定函数的参数   在调用目标函数时。

这是一个有效的解决方案。我做了一些小的调整,以便您使用function IMdraw(div) { this.div = div; this.div.addEventListener('mousedown', this.mousedown.bind(this)); } IMdraw.prototype = { onMouseMove: function (fn) { this.div.addEventListener('mousemove', fn); }, move1: function(arg, e) { console.log('move1'); console.log(e.offsetX, "Passed argument: " + arg); console.log(e.offsetY, "Passed argument: " + arg); }, move2: function(arg, e) { console.log('move2'); console.log(e.offsetX, "Passed argument: " + arg); console.log(e.offsetY, "Passed argument: " + arg); }, mousedown: function(e) { console.log(this.div); var arg = 3; // The e argument represents the mousedown event that was fired. It only happens // once, when you click the mouse. It won't happen again when you move the mouse // so the values associated with it don't change on move1 and move2. // Instead, don't pass the event object at all (let that happen organically as it // normally does) and pass just the extra data you want to pass. This extra argument // will be the FIRST argument recieved by the bound function and the event will be // the SECOND. this.div.addEventListener("mousemove", this.move1.bind(this, arg)); this.div.addEventListener("mousemove", this.move2.bind(this, arg)); } } var obj = new IMdraw(document.querySelector('div'));而不是<div style="width:500px; height:500px; background: blue;"> </div>,这是更现代和基于标准的。

let mainMenu() = ["1. list item one",itemOne
                  "2. list item two",itemTwo
                  "3. list item three",itemThree
                  "4. list item four",itemFour
                  "0. Exit",exitApplication] 
                  |> Map.ofList
mainMenu() 
|> Seq.iter(fun keyValuePair -> 
    Console.WriteLine (sprintf "%s" (keyValuePair.Key |> string)))