RP Niemeyer 的回答是迈向可扩展解决方案的良好开端。但是,它不允许您在“条件”选项中包含包含可观察对象的表达式,当这些可观察对象随时间变化时,它将被重新评估。
例如,此绑定只计算一次“条件”表达式(当 init 回调执行时),并且随着可观察值的变化而无法正常工作:
<span data-bind="clickIf: { action: doSomething, condition: (isEnabled() == true && anotherObservable() == true) }">Test</span>
为了让这个绑定接受包含 observables 的表达式,并根据该表达式的最新值正确执行,您需要像这样重构绑定处理程序:
ko.bindingHandlers.clickIf = {
init: function (element, valueAccessor) {
// Hold state of options so that the 'update' callback can effectively
// 'pass in' new evaluated 'condition' expressions (as observables change) to the wrappedHandler.
element.ko_clickIfOptions = ko.utils.unwrapObservable(valueAccessor());
var wrappedHandler = function (data, event) {
// "ko_clickIfOptions.condition" will get us the current value of a 'condition'
// expression since the 'update' callback updates these options
var condition = ko.utils.unwrapObservable(element.ko_clickIfOptions.condition);
if (condition) {
element.ko_clickIfOptions.action.call(data, data, event);
}
};
ko.applyBindingsToNode(element, { click: wrappedHandler });
},
// When the value of any observable in your expression changes, we grab 'options'
// again so that the wrappedHandler will have the latest value of the expression
update: function (element, valueAccessor) {
element.ko_clickIfOptions = ko.utils.unwrapObservable(valueAccessor());
}
};
使用此实现,即使“条件”表达式中的任何可观察值发生变化,上面列出的示例也可以正确运行。