Knockout.js文本框keyup事件中data.nameValue()未定义问题求助
嘿,我来帮你搞定这个问题!先从你代码里的一个小bug说起——你的input标签data-bind属性里多了个多余的逗号:value: nameValue, , event:,这个语法错误可能会让Knockout解析绑定的时候出问题,先把它删掉,修正后的input代码应该是:
<input type="text" class="form-control textbox" data-bind="value: nameValue, event: { 'keyup': checkIfTextBoxEmpty }" />
接下来,聊聊为什么data.nameValue()会是undefined,主要有两个常见原因,对应不同的解决办法:
1. 事件函数里的data不是你的ViewModel实例
Knockout事件绑定里的data参数默认是当前绑定上下文的$data,但如果这个input嵌套在foreach或者其他子绑定上下文里,data就会变成子对象,自然找不到nameValue这个属性。
解决办法有两种,选哪种看你的页面结构:
方法一:显式指定事件函数的上下文
在data-bind里用$root或者$parent(根据你的ViewModel层级)来调用事件函数,确保传递的是根ViewModel:<input type="text" class="form-control textbox" data-bind="value: nameValue, event: { 'keyup': $root.checkIfTextBoxEmpty }" />这样事件函数里的
data就会是你的根ViewModel实例,data.nameValue()就能正常获取值了。方法二:直接用ViewModel的
self变量
你已经在ViewModel里用self保存了this的引用,完全可以跳过data参数,直接访问self.nameValue(),这样就不用管上下文的问题了:self.checkIfTextBoxEmpty = function (data, event) { // 直接用self访问,避免data上下文的坑 if(self.nameValue() === '') { // 隐藏无效值错误的span,比如如果你的span用了Knockout的visible绑定: // self.showInvalidError(false); // 要是想用jQuery直接操作DOM(虽然更推荐用声明式绑定): // $(event.target).next('.invalid-error-span').hide(); } };
2. nameValue没被正确声明为Observable
如果你的ViewModel里没有把nameValue定义成Knockout的Observable,那不管怎么访问data.nameValue()都会是undefined。请确认你的ViewModel里有这段代码:
function MyViewModel() { var self = this; // 必须声明为observable,才能用()获取/设置值 self.nameValue = ko.observable(''); // 你的其他属性和方法... self.checkIfTextBoxEmpty = function (data, event) { // ... }; } ko.applyBindings(new MyViewModel());
额外的优化小建议
其实你不用手动绑定keyup事件来处理错误提示的显示隐藏,Knockout的验证插件(比如Knockout Validation)本身就支持根据字段状态自动切换错误提示。你可以给nameValue添加上验证规则,然后让错误提示的span通过visible绑定关联验证状态,这样更符合Knockout的声明式编程风格,也能减少手动操作DOM的代码~
内容的提问来源于stack exchange,提问作者aman

