我创建了一个基于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。但是,根据我的理解,这不应该适用于bootstrap-toggle,因为此组件会在input
元素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。
我非常感谢你理解这一点!
答案 0 :(得分:0)
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'
因为它实际上什么也没做。
对此没有任何直接的解决方案,这些CSS框架往往只是非常具有侵入性的javascript。我通常建议不要包含他们的脚本,并在Aurelia本地查找(或实现)它们。这样做非常容易,而且工作得更好。