Angular中如何为keydown事件处理函数传递自定义参数?
报错根本原因
当前写法存在两个核心问题,直接触发了抛出的异常:
- 代码执行到
$document.on('keydown', handleKeyPress($element, event));这一行时,会立刻调用handleKeyPress函数,而非把函数引用传递给事件绑定方法。该函数没有设置返回值,执行完成后返回结果是undefined。事件绑定方法拿到的第二个参数是undefined,Angular内部尝试对这个值执行call方法时,就会抛出Uncaught TypeError: Cannot read property 'call' of undefined的错误。 - 代码里的
handleKeyPress是通过var声明的函数表达式,存在变量提升特性。事件绑定代码执行时,后面的函数赋值逻辑还没跑,此时就算直接传handleKeyPress引用,拿到的值也是undefined,同样会触发相同报错。
可落地的解决方法
- 用闭包包裹一层事件回调,保留事件对象的入参通道
不要直接执行目标函数,给事件绑定传一个匿名回调函数,等keydown事件触发时,在匿名回调内部再调用handleKeyPress,手动传入外层作用域的$element和系统生成的event对象:// 把函数定义放在绑定代码前面,避免未赋值的问题 var handleKeyPress = function (element, event) { var inputElement = element; var keyCode = (event.which) ? event.which : event.keyCode; // 业务逻辑 }; $document.on('keydown', function(event) { handleKeyPress($element, event); }); - 用
Function.prototype.bind绑定固定参数
bind方法会返回一个全新的函数,不会立刻执行原函数,还可以提前把固定参数传入,剩余的参数会等新函数被调用时自动补全:
这种写法的执行逻辑是:keydown触发时,事件系统会把event对象作为参数传给bind生成的新函数,新函数会把event补到入参列表的末尾,最终实际调用handleKeyPress时,参数顺序就是var handleKeyPress = function (element, event) { var inputElement = element; var keyCode = (event.which) ? event.which : event.keyCode; // 业务逻辑 }; // bind第一个参数为绑定的this指向,不需要修改this时传null即可;第二个参数开始是提前传入的固定参数 $document.on('keydown', handleKeyPress.bind(null, $element));($element, event),完全匹配函数定义的参数要求。 - 调整函数声明方式,规避变量提升带来的undefined问题
把函数表达式改成函数声明写法,这种写法会完整提升整个函数定义,哪怕把事件绑定代码写在函数定义前面,也不会出现绑定时函数未定义的问题:// 函数声明写法,会完整提升整个函数逻辑 function handleKeyPress(element, event) { var inputElement = element; var keyCode = (event.which) ? event.which : event.keyCode; // 业务逻辑 } $document.on('keydown', handleKeyPress.bind(null, $element));
内容的提问来源于stack exchange,提问作者ramya m
相关产品推荐
相关产品推荐

