Knockout.js似乎是在破坏我的jQuery事件处理程序,多么粗鲁

Mik*_*sen 36 javascript jquery knockout.js

好吧,我一直试图解开这个烂摊子几个小时,现在已经无处可去,类似于追逐尾巴的狗.这是情况.

我正在使用Knockout.js作为我的UI,它本身很好用.但是,我正在尝试使用一些第三方代码,使下拉列表和复选框看起来很漂亮.实际上我甚至不确定这是第三方库还是我们设计师写的东西.此代码隐藏了真实的复选框,并将其替换为<span />通过CSS模仿复选框的伪造.该click跨度的事件触发change的实际复选框的事件:

// 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);
Run Code Online (Sandbox Code Playgroud)

这实际上适用于Knockout.js,因为Knockout将侦听该事件处理程序.换句话说,当用户单击假复选框时,绑定的Knockout模型会更新.然而,有什么工作是更新模型.如果我打电话:

model.SomeValue(!curValue); // SomeValue is bound to a checkbox, flip its value
Run Code Online (Sandbox Code Playgroud)

模型会更新,但虚假的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;
Run Code Online (Sandbox Code Playgroud)

基本上,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);
      }
   };
Run Code Online (Sandbox Code Playgroud)

而不是设置element.checked,而是调用.prop('checked', value)并触发更改事件.但是,这不起作用.这是我目前所知道的:

  1. 如果我从等式中删除Knockout.js,$(element).prop('checked', value).trigger('change');效果非常好.所以,knockout.js正在调整事件的一些方式.它解除了那个事件处理程序吗?
  2. 我已经证实$(element)的是同样的事情this.$input在假复选框绑定代码.我可以在这个元素上设置其他expando属性,然后它们就会显示出来.
  3. 我尝试了一些方法来尝试调试Knockout.js和jQuery以查看事件是否仍然绑定,但是我还没有真正得到这种方法.我的预感是,Knockout.js以某种方式用change自己的内部处理程序替换了事件处理程序,并删除了现有的绑定.我还没有办法确认这一点.

我的问题:主要是,我正在寻找解决这个问题的方法.Knockout.js是否删除change了在应用模型之前存在的现有事件?调试此代码并弄清楚究竟发生了什么的下一步是什么?

Hug*_*lva 0

Try triggering and listening also for a custom event:

element.checked = value;
element.dispatchEvent(new Event("forcedChange"));
Run Code Online (Sandbox Code Playgroud)