代码之家  ›  专栏  ›  技术社区  ›  user4282812

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

  •  1
  • user4282812  · 技术社区  · 7 年前

    我正在尝试重写一个没有jQuery的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>

    正如您在蓝色div中单击并在div中移动光标时所看到的,在 move2 功能 offsetX offsetY 不更新,但在 move1 作用

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

    1 回复  |  直到 4 年前
        1
  •  1
  •   Scott Marcus    7 年前

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

    • 具有 move1 ,你没有通过任何东西,所以 e 正确指向 这个 mousemove 自动传递给事件的事件 回调函数。 arg 没有通过,所以 精氨酸 (内部 移动1 )可能是 undefined .
    • 具有 move2 ,您通过传递自己的参数来干扰事件对象的自动传递。这个 e 你是谁 传递是来自 mousedown 事件,但事实并非如此 更新时间 移动鼠标 发生,因此您始终可以看到鼠标单击时的偏移。你确实及格了 精氨酸 移动2 这本来是可行的。

    解决方案是根本不传递事件对象,让它像通常那样自动传递,只传递您需要的任何额外数据( 精氨酸 但在这种情况下,您传递的参数将是函数收到的第一个参数,而事件将是最后一个参数(与通常发生的情况相反)。

    来自 MDN :

    语法 : fun.bind(thisArg[, arg1[, arg2[, ...]]])

    参数

    thisArg公司

    作为this参数传递给目标函数的值 当调用绑定函数时。如果边界为 函数是使用新算子构造的。

    arg1,arg2。。。

    的参数 预编 到提供给绑定函数的参数 调用目标函数时。

    这是一个有效的解决方案。我做了一些小的调整,以便您使用 addEventListener 而不是 onmousemove ,它更现代化,更标准化。

    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>