从 addEventListener 中提取带有此关键字的绑定函数

extracting bound function with this keyword out of addEventListener

我想修改一个 library function 如下所示:

this.map.getContainer().addEventListener('touchstart', this.fire.bind(map, 'mousedown'));

现在(如果我做对了),该函数侦听触摸事件,如果发生触摸事件,则调度相应的鼠标事件。所以它告诉地图对象像处理鼠标事件一样处理触摸事件。

this.map.on('mousedown', this.eventHandlers.mouseDown);
this.eventHandlers = {
    mouseDown: this.events.mouseDown.bind(this),
};

我想修改上面的函数,让它区分单指触摸事件和多点触摸事件,像这样:

element.addEventListener('touchstart', onTouchStart);
function onTouchStart(e) { 
    if (e.touches.length > 1) { foo() } else { this.fire.bind(map, 'mousedown') }
};

但是,仅仅将上面的侦听器函数放在那里是行不通的。我尝试使用 e.currentTarget 并创建一个 var otherThis = this 然后用 otherThis 替换它,但它没有用。

我收到以下错误:

Uncaught TypeError: Cannot read property 'bind' of undefined at HTMLDivElement.onTouchStart

非常感谢帮助!

这里:

function onTouchStart(e) { 
    if (e.touches.length > 1) { foo() } else { this.fire.bind(map, 'mousedown') }
};

问题是 this.fire.bind(map, 'mousedown')。这段代码没有副作用,它只是定义了一个函数。参见 bind。但实际上并没有调用它。

要调用它,您可以使用:

this.fire('mousedown');

这是 XY problem 的实例。

不需要将触摸事件转化为鼠标事件(touchstartmousedown,touchmovemousemove,touchendmouseup) 或者反之亦然:浏览器已经为您完成了

我强烈建议您观看 "Getting Touchy" presentation from 2015 as well as reading the corresponding slide deck。它深入解释了不同的浏览器如何在触摸事件的同时发送鼠标(和指针)事件。

即使您仅在触摸事件的某些条件下发送 mousedown/up/move,您也会收到 重复 mousedown/up/move 单次触摸事件。


另一方面:此处绑定事件处理程序的简洁方法...

element.addEventListener('touchstart', onTouchStart);
function onTouchStart(e) { 
    if (e.touches.length > 1) { foo() } else { this.fire.bind(map, 'mousedown') }
};

...会...

element.addEventListener('touchstart', onTouchStart.bind(this));
function onTouchStart(e) { 
    if (e.touches.length > 1) { foo() } else { this.fire('mousedown') }
};

请注意如何将 bind() 调用应用于事件处理程序函数,而 不会 应用于事件处理程序内部的函数调用。这使得事件处理程序内部的 this 的值成为 bind().

的参数

"The Leaflet way" 会是...

L.DomEvent.on(element, 'touchstart', onTouchStart, this)

...这是 bindaddEventListener 的两个包装器。 L.DomEvent 还处理浏览器怪癖(dblclick 在某些情况下在触摸屏上),并翻译非标准 IE10 的 MSPointerDown (等),以便 touch* 在 Win7 机器上的事件使用 IE10 和触摸屏即可。