TypeError:只能在Safari上的Node实例上调用Node.addEventListener

时间:2016-06-17 10:46:40

标签: javascript reactjs safari

我的React组件中有这段代码禁用了“enter”键。

export const attachDisableEnterEvent = (ref) => {
  const node = ReactDOM.findDOMNode(ref);
  // Evergreen event listener || IE8 event listener
  const addEvent = node.addEventListener || node.attachEvent;
  addEvent('keypress', _disableEnter, false);
}

它适用于Chrome / Firefox,但不适用于Safari。在Safari上我得到: -

  

TypeError:只能在Node

的实例上调用Node.addEventListener

我只能这样做(在各方面): -

addEvent.call(node, 'keypress', _disableEnter, false);

只是想知道为什么addEventListener的实施在Chrome和&苹果浏览器。 Chrome上的Node.addEventListener似乎只是直观地将this绑定到定义它的节点实例。

1 个答案:

答案 0 :(得分:4)

这可能与我们拥有以下内容的原因相同:

var log = console.log;
log('foo') // TypeError

相反,我们必须:

var log = console.log.bind(console); // bind console.log function to it's proper context
log('foo') // 'foo'

在您的情况下,请致电

addEvent('keypress', _disableEnter, false);

导致上下文成为窗口对象(隐式)。

通常,当您打算将函数传递给其他人时,您总是希望首先将函数绑定到拥有对象。浏览器实现对于每个浏览器都是不同的,因此这是确保其统一工作的最佳方式。

在控制台的情况下,我相信.log是指控制台对象本身的其他实例方法。因此在Safari中,node.addEventListener函数可能以需要仅在node上定义的其他函数的方式实现,并且它们可能也会提供更具描述性的错误消息。

所以你应该这样做:

const addEvent = node.addEventListener || node.attachEvent;
const boundAddEvent = addEvent.bind(node);
// use boundAddEvent however you like anywhere, or .call like you did