KnockoutJS 绑定未在复选框单击事件中更新
KnockoutJS Binding not updating in checkbox click event
我 运行 遇到了 KnockoutJS 的问题,数据绑定似乎没有按预期更新。
在我的视图模型中,我有一个对象数组,其中包含我初始化为 True 的 Enabled 属性,并将 属性 绑定为在带有单击处理程序 CheckItems 的复选框上启用:
self.Answers(data.filter(function (step) {
if (step.Type == 0) {
step.Enabled = true;
return true;
}
else {
return false;
}
}));
...
<ul data-bind="foreach: $root.Answers">
<input type="checkbox" data-bind="click: $root.CheckItems, ..., enable: Enabled>
</ul>
一切正常,直到 CheckItems 处理程序运行并且我尝试将 Enabled 属性 设置为 false:
self.CheckItems = function (step) {
...
self.Answers().forEach(function (option) {
<call my handler>.done(function (data) {
option.Enabled = data;
}
);
});
// EDIT: added valueHasMutated() call here
self.Answers.valueHasMutated();
return true;
}
当我点击 return true 时,我可以检查 self.Answers() 对象,它显示应该禁用的答案有 Enabled = false(正确),但是一旦我们处理程序,复选框的 none 被禁用,单击存在的任何其他复选框并通过处理程序显示已启用 属性 似乎已重置为 True。我三重检查并确保在单击复选框之间的代码中的任何地方都没有其他内容触及已启用 属性。
绑定本身似乎也有效,因为当我将初始启用设置切换为 false 时,所有复选框都被禁用。
我也在脚本中的其他各个地方对 self.Answers 数组进行更改,这些都很好,当进行更改时,它会进入淘汰赛-latest.debug.js 并着陆在 notifySubscribers 函数中进行适当的更新。也许knockout中输入框的点击事件有什么特别之处?
有什么想法吗?总体上对 Knockout 还是相当陌生,但我认为这就是重点,我可以在 Answers() 可观察数组中更新 属性,它会在相应的 UI.[=12= 中更新]
编辑:根据评论,我尝试在编辑完成后调用 valueHasMutated(),但它仍然没有正确更新。
Edit2:尝试制作 self.Answers 数组的副本,执行处理程序调用以更新启用,然后使用 self.Answers(newAnswers) 进行设置,这得到了相同的结果。
我被告知问题的发生是因为 CurrentAnswers() 中对象的属性也不可观察。由于数组本身没有变化,所以 knockout 没有注册它必须重新绑定任何东西,这就是为什么调用 valueHasMutated() 没有改变任何东西,因为数组在 CheckItems() 之前和之后看起来完全一样数组的观点(也是为什么用数组的副本更新不起作用,同样的问题)。当将 CurrentAnswers() 设置为空白数组 (self.CurrentAnswers([])),然后将其设置为更新后的值时,由于 KO 识别出实际的数组更改,事情发生了适当的变化。
我最终使用的解决方案是利用 ko.mapping.fromJS() 方法用具有可观察属性的对象填充 CurrentAnswers()。在 HTML 和 JS 中进行一些语法更改以正确引用新的可观察对象后,一切正常。
我 运行 遇到了 KnockoutJS 的问题,数据绑定似乎没有按预期更新。
在我的视图模型中,我有一个对象数组,其中包含我初始化为 True 的 Enabled 属性,并将 属性 绑定为在带有单击处理程序 CheckItems 的复选框上启用:
self.Answers(data.filter(function (step) {
if (step.Type == 0) {
step.Enabled = true;
return true;
}
else {
return false;
}
}));
...
<ul data-bind="foreach: $root.Answers">
<input type="checkbox" data-bind="click: $root.CheckItems, ..., enable: Enabled>
</ul>
一切正常,直到 CheckItems 处理程序运行并且我尝试将 Enabled 属性 设置为 false:
self.CheckItems = function (step) {
...
self.Answers().forEach(function (option) {
<call my handler>.done(function (data) {
option.Enabled = data;
}
);
});
// EDIT: added valueHasMutated() call here
self.Answers.valueHasMutated();
return true;
}
当我点击 return true 时,我可以检查 self.Answers() 对象,它显示应该禁用的答案有 Enabled = false(正确),但是一旦我们处理程序,复选框的 none 被禁用,单击存在的任何其他复选框并通过处理程序显示已启用 属性 似乎已重置为 True。我三重检查并确保在单击复选框之间的代码中的任何地方都没有其他内容触及已启用 属性。
绑定本身似乎也有效,因为当我将初始启用设置切换为 false 时,所有复选框都被禁用。
我也在脚本中的其他各个地方对 self.Answers 数组进行更改,这些都很好,当进行更改时,它会进入淘汰赛-latest.debug.js 并着陆在 notifySubscribers 函数中进行适当的更新。也许knockout中输入框的点击事件有什么特别之处?
有什么想法吗?总体上对 Knockout 还是相当陌生,但我认为这就是重点,我可以在 Answers() 可观察数组中更新 属性,它会在相应的 UI.[=12= 中更新]
编辑:根据评论,我尝试在编辑完成后调用 valueHasMutated(),但它仍然没有正确更新。
Edit2:尝试制作 self.Answers 数组的副本,执行处理程序调用以更新启用,然后使用 self.Answers(newAnswers) 进行设置,这得到了相同的结果。
我被告知问题的发生是因为 CurrentAnswers() 中对象的属性也不可观察。由于数组本身没有变化,所以 knockout 没有注册它必须重新绑定任何东西,这就是为什么调用 valueHasMutated() 没有改变任何东西,因为数组在 CheckItems() 之前和之后看起来完全一样数组的观点(也是为什么用数组的副本更新不起作用,同样的问题)。当将 CurrentAnswers() 设置为空白数组 (self.CurrentAnswers([])),然后将其设置为更新后的值时,由于 KO 识别出实际的数组更改,事情发生了适当的变化。
我最终使用的解决方案是利用 ko.mapping.fromJS() 方法用具有可观察属性的对象填充 CurrentAnswers()。在 HTML 和 JS 中进行一些语法更改以正确引用新的可观察对象后,一切正常。