好的,我已经尝试解开这个烂摊子几个小时了,但一无所获,类似于狗追逐它的尾巴。这是情况。
我在我的 UI 中使用了 Knockout.js,它本身就很好用。但是,我正在尝试使用一些第三方代码,使下拉菜单和复选框看起来都很漂亮。实际上,我什至不确定这是第三方库还是我们的设计师写的东西。此代码隐藏了真正的复选框,并将其替换为<span />
通过 CSS 模仿复选框的虚假复选框。span的事件click
触发change
了真实checkbox的事件:
// this code updates the fake UI
this._changeEvent = function() {
self.isChecked = self.$input.is(':checked');
self._updateHTML(false, true);
jQuery(self).trigger('change');
};
// when the user clicks the fake checkbox, we trigger change on the real checkbox
this.$fake.on('click', function(e) {
e.preventDefault();
self.$input.click().trigger('change');
});
// Bind _changeEvent to the real checkbox
this.$input.change(this._changeEvent);
这实际上适用于 Knockout.js,因为 Knockout 将侦听该事件处理程序。换句话说,当用户点击虚假复选框时,绑定的 Knockout 模型会更新。但是,不起作用的是更新模型。如果我打电话:
model.SomeValue(!curValue); // SomeValue is bound to a checkbox, flip its value
模型得到更新,但假 UI 没有更新。我已将此问题追溯到ko.bindingHandlers.checked.update
执行以下操作的代码:
// When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
element.checked = value;
基本上,该element.checked
属性已设置,但没有触发任何事件。因此,该_changeEvent
函数永远不会被调用。所以,我实现了自己的ko.bindingHandlers.checked.update
函数,它是内置函数的副本。理论上,这就是我需要做的所有事情:
ko.bindingHandlers.checked.update = function (element, valueAccessor)
{
var value = ko.utils.unwrapObservable(valueAccessor());
if (element.type == "checkbox")
{
if (value instanceof Array)
{
// When bound to an array, the checkbox being checked represents its value being present in that array
element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
}
else
{
// When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
//element.checked = value;
$(element).prop('checked', value).trigger('change'); // <--- this should work!
}
}
else if (element.type == "radio")
{
element.checked = (element.value == value);
}
};
我没有设置element.checked
,而是调用.prop('checked', value)
并触发更改事件。但是,这是行不通的。到目前为止,这是我所知道的:
- 如果我从等式中删除 Knockout.js,则
$(element).prop('checked', value).trigger('change');
效果很好。所以,knockout.js 以某种方式搞砸了这个事件。是否取消绑定该事件处理程序? - 我已经确认与假复选框绑定代码中
$(element)
的内容相同this.$input
。我可以在这个元素上设置其他 expando 属性,它们就会显示出来。 - 我尝试了一些方法来尝试调试 Knockout.js 和 jQuery 以查看事件是否仍然绑定,但是我并没有真正使用这种方法。我的预感是 Knockout.js 不知何故用
change
自己的内部事件处理程序替换了事件处理程序,并且现有的绑定被删除了。我还没有找到方法来确认这一点。
我的问题:主要是,我正在寻找解决此问题的方法。Knockout.js 是否会删除change
应用模型之前存在的现有事件?调试此代码并弄清楚到底发生了什么的下一步是什么?