基于 bootstrap-toggle 的自定义元素不更新属性绑定

Custom element based on bootstrap-toggle not updating attribute binding

我创建了一个基于 bootstrap-toggle 的自定义元素,如下所示:

toggle.ts:

import {bindingMode, bindable, customElement} from "aurelia-framework";

@customElement('toggle')
export class Toggle {
  @bindable({ defaultBindingMode: bindingMode.twoWay }) checked;
  input;

  attached() {
    $(this.input).bootstrapToggle();
  }
}

toggle.html:

<template>
  <require from="bootstrap-toggle/css/bootstrap2-toggle.min.css"></require>
  <require from="bootstrap-toggle"></require>

  <input ref="input" data-toggle="toggle" type="checkbox" checked.bind="checked">
</template>

问题是当通过 UI 切换开关时,checked 属性的绑定永远不会更新。我知道将 Aurelia 与基于 jQuery 的组件一起使用时的常见陷阱,如 here. However, in my understanding this should not apply to bootstrap-toggle, as this component triggers a change event on the input element on toggle 所述。我已验证此更改事件会冒泡到我的自定义组件。

我目前使用的解决方法是:

toggle.ts:

import {bindingMode, bindable, customElement} from "aurelia-framework";

@customElement('toggle')
export class Toggle {
  @bindable({ defaultBindingMode: bindingMode.twoWay }) checked;
  input;

  attached() {
    $(this.input).bootstrapToggle().on('change', (event) => this.checked = event.target.checked);
  }
}

但是,我不明白为什么这是必要的。 我已经创建了一个基于 Aurelia 的导​​航骨架的测试项目,可以下载 here

如果能帮助我理解这一点,我将不胜感激!

jquery 使用的事件侦听器使用捕获阶段,并且可能会执行 preventDefault 或这些行中的某些内容以防止事件冒泡备份。

此行调度的更改事件:if (!silent) this.$element.change() 实际上并未传播到冒泡阶段。 Aurelia 使用气泡阶段,因此永远不会收到事件。

如果您像这样在浏览器控制台中手动发送一个,您会看到不同之处: document.querySelector("[data-toggle]").dispatchEvent(new CustomEvent("change"));

这将导致调用适当的侦听器并更新绑定 属性。

此行的作用:.on('change', (event) => this.checked = event.target.checked); 还在捕获阶段添加一个侦听器,这当然会起作用。但是你也可以删除 checked.bind='checked' 因为那实际上什么都不做。

不一定有任何 straight-forward 解决这个问题,这些 CSS 框架往往具有非常侵入性 javascript。我通常建议不要包含他们的脚本,而是在 Aurelia 中本地寻找(或实现)它们。这样做非常容易,而且效果更好。