当 ko 解析绑定时,它会检查表达式是否是可观察的,正如您所知,它是一个函数。如果表达式是可观察的,ko 会自动解包值以显示它,但它也允许订阅和通知。
在这种情况下,当 ko 解析表达式时,它会找到一个值,而不是 observable,因此,它也可以正常工作以显示该值(值更改 > 视图更新)。但是,您将失去从视图到值的绑定(输入值更改 > 可观察的未更新),因为它不是可观察的。有关更多详细信息,请参阅下面的说明和片段。
customProperty
是一个函数,特别是 a ko.observable
,这意味着它支持订阅和通知,除了使用()
or(newValue)
语法读取或设置值
注意:使用和不使用括号之间的区别是巨大的。如果你这样做:
<input type="text" data-bind="value: customProperty" ...
正如我在 1 中解释的那样,ko 发现这customProperty
是一个 observable,因此当用户更改 中的值时input
,新值将被写回 observable。如果你这样做:
<input type="text" data-bind="value: customProperty()" ...
正如我在 2 中解释的那样,ko 找到了一个值,而不是一个可观察值。因此,如果用户通过键入来更改 的值input
,则新值不会反馈给可观察对象,因为 ko 不知道它是可观察对象。(但如果更新了可观察值,则视图会发生变化,因为在表达式评估期间发现并订阅了依赖项)。
var vm = {
customProperty: ko.observable(10)
};
ko.applyBindings(vm);
body {
font-family: Segoe, Arial
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
data-bind="value: customProperty()"<br/>
<input type="text" data-bind="value: customProperty(), valueUpdate: 'keyup'"/><br/>
If you change the input text, customProperty is not updated
<br/><br/>
data-bind="value: customProperty"<br/>
<input type="text" data-bind="value: customProperty, valueUpdate: 'keyup'"/><br/>
If you change the input text, customProperty changes
<br/><br/>
customProperty value: <span data-bind="text: customProperty"/>
在其他框架(如 Angular)中,它不使用函数,而是使用带有 JavaScript setter和getter的属性,因此语法永远不需要括号。带有 settes 和 getter 的属性可以像任何其他属性一样被读取和写入,但在后台运行 setter 或 getter 中的代码,从而允许订阅和通知发生。
注2(因为评论中有问题)。你可以这样想:当 ko 解析一个绑定表达式时,它会立即计算整个表达式并检查结果是否是可观察的。因此,当您有这样的表达式时:customProperty == 10
,当 ko 评估它时,它发现它不是可观察的(而是布尔值)并且不需要额外的步骤来获取值。结果总是错误的,因为customProperty
是 a function
,因此是 '!= 10'。如果您将表达式更改为这个:customProperty() == 10
自定义属性值将由 展开()
,并且比较将按预期进行。顺便说一句,尽量不要在绑定表达式中包含代码:在模型中使用计算的 observables(如果可能的话,最好是纯计算的)要好得多。
注释 2 的控制台实验
类型:var vm = {customProperty: ko.observable(10)}
创建视图模型。
输入: vm.customProperty()
,你会看到10
结果。
输入: vm.customProperty
,你会看到function ...
结果。
输入:vm.customProperty() == 10
,你会看到true
(难怪,10 == 10
)
输入:vm.customProperty == 10
,你会得到false
(因为function != 10
)
此外,键入ko.isObservable(vm.customProperty)
,您将看到true
. 这就是ko所做的。所以 ko 知道它必须解开这个值。输入ko.unwrap(vm.customProperty)
,你会看到10
最后,输入ko.isObservable(vm.customProperty == 10)
or ko.isObservable(vm.customProperty() == 10)
。在这两种情况下,您都会得到false
,因为表达式bool
在两种情况下都是 a ,而不是可观察的函数。Ko 没有分解表达式并逐个检查它。这将是在第一个表达式中发现customProperty
可观察的并且应该被解包的唯一方法。但是ko不是那样做的。
注 3:表达式,作为计算的 observable,在原始评估中使用 observable 属性并更改其值时会重新评估。请注意,如果在第一次评估中您只访问一个 observable 属性,即使代码包含对其他 observable 的引用,它也只会在访问的 observable 更改其值时重新评估。不会“观察到”其他可观察对象的变化。典型的情况是if
依赖于不同的可观察对象,具体取决于执行的分支