使用类似
的绑定<div data-bind="myBinding: { ... }, enable: isEnable() && isThatEnabled()"></div>
在调试JS代码时,当我查看myBinding的init中的allBindings时,通常定义如下:
init: function (element, valueAccessor, allBindings, viewModel, bindingContext)
我看到allBindings.enable
是一个布尔值,它是isEnable() && isThatEnabled()
的实际计算值。它不是一个可观察的,就像我期望KO基于布尔表达式创建一样。
我的问题是为什么它不是一个可观察的?
是否可以遵守“启用”功能。在这种情况下从myBinding
绑定?
我看到3个选项:
定义自定义enable
绑定:
<div data-bind="myBinding: { ... }, myEnable: isEnable() && isThatEnabled()"></div>
有一个&#39;启用&#39; myBinding
的参数:
<div data-bind="myBinding: { enable: isEnable() && isThatEnabled() }"></div>
在HTML中使用计算的observable:
data-bind="myBinding: bar, enable: ko.computed(function () { return foo() && foo2(); })"
第二个对我来说似乎最合理。
var model = {
foo: ko.observable(true),
foo2: ko.observable(true),
bar: ko.observable(1)
};
ko.bindingHandlers.myBinding = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
var valueUnwrapped = ko.unwrap(value);
element.innerHTML += ko.isObservable(allBindings().enable);
// how unfortunate, 'enable' binding value is not observable
// how to listen to 'enable' binding changes right here?
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
var valueUnwrapped = ko.unwrap(value);
}
};
function onload() {
ko.applyBindings(model);
}
&#13;
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body onload="onload()">
<input type="checkbox" data-bind="checked: foo">
<input type="checkbox" data-bind="checked: foo2">
<button data-bind="myBinding: bar, enable: foo() && foo2()">Is 'enable' binding observable: </button>
</body>
</html>
&#13;
答案 0 :(得分:1)
来自ko来源:
// Use of allBindings as a function is maintained for backwards compatibility, but its use is deprecated
function allBindings() {
return ko.utils.objectMap(bindingsUpdater ? bindingsUpdater() : bindings, evaluateValueAccessor);
}
// The following is the 3.x allBindings API
allBindings['get'] = function(key) {
return bindings[key] && evaluateValueAccessor(getValueAccessor(key));
};
allBindings['has'] = function(key) {
return key in bindings;
};
如果你致电allBindings()
,它会解开所有绑定的值。因此,如果您从计算函数访问它(例如从绑定的update
方法),计算函数将订阅所有绑定更改的更新。
您无法直接访问observable,但可以使用ko.computed
var enableObs = ko.computed(function() {return allBindings().enable;});
注意:不推荐使用allBindings 作为功能!因为如果从update
方法调用它,它将在其他绑定中的任何更新上执行。所以最好:
var enableObs = ko.computed(function() {return allBindings.get('enable');});
查看myBinding
和myBinding2
行为的差异。
您也可以从update
方法订阅更新而不计算(myBinding3)。
var model = {
foo: ko.observable(true),
foo2: ko.observable(true),
text: ko.observable("changeme"),
log: ko.observableArray([])
};
ko.bindingHandlers.myBinding = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
var num=0;
var valueUnwrapped = ko.unwrap(value);
var enableObs = ko.computed(function() {
// Note this computed executes on update of any binding. Not only for `enable` binding. Increment for show it.
return allBindings().enable.toString() + num++;
});
enableObs.subscribe(function() {
// if you remove counter from computed function this function will execute only on `enable` binding updates.
element.innerHTML = ko.unwrap(enableObs).toString();
});
}
};
ko.bindingHandlers.myBinding2 = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var value = valueAccessor();
var num=0;
var valueUnwrapped = ko.unwrap(value);
var enableObs = ko.computed(function() {
return allBindings.get("enable").toString() + num++;
});
enableObs.subscribe(function() {
element.innerHTML = ko.unwrap(enableObs).toString();
});
}
};
var tmp = 0;
ko.bindingHandlers.myBinding3 = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
element.innerHTML = allBindings.get('enable').toString() + tmp++;
}
};
function onload() {
ko.applyBindings(model);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body onload="onload()">
<input type="text" data-bind="value: text, valueUpdate: 'keyup'">
<input type="checkbox" data-bind="checked: foo">
<input type="checkbox" data-bind="checked: foo2">
<button data-bind="myBinding, enable: foo() && foo2(), value: text()">Do smth</button>
<button data-bind="myBinding2, enable: foo() && foo2(), value: text()">Do smth</button>
<button data-bind="myBinding3, enable: foo() && foo2(), value: text()">Do smth</button>
</body>
</html>
<强> OLD:强>
init: function (element, valueAccessor, allBindings, viewModel, bindingContext)
如果您想要订阅 - 请改用update
功能。
请参阅示例:http://jsbin.com/foxezidada/edit
和文档:http://knockoutjs.com/documentation/custom-bindings.html
我的问题是为什么它不是一个可观察的?
https://github.com/knockout/knockout/blob/master/src/binding/bindingAttributeSyntax.js
var getValueAccessor = bindingsUpdater
? function(bindingKey) {
return function() {
return evaluateValueAccessor(bindingsUpdater()[bindingKey]);
};
} : function(bindingKey) {
return bindings[bindingKey];
};
它在这里评估。