何时在数据绑定表达式中使用或不使用括号
When to use or not use parentheses with observables in data-binding expressions
我已经看到其他线程,但我仍然感到困惑,我想我在这里提出了一个不同的案例。
我正在使用显示模式 return 我的 HTML 文档的视图模型对象。因此,我有一个看起来像这样的视图模型对象:
var vm = function() {
var customProperty = ko.numbericObservable(0);
return {
customProperty: customProperty
};
} ();
由此,您可以看到 customProperty 被分配给初始值为 0 的 Knockout numeric observable。
在包含上述 JavaScript 的 HTML 文档中,我有一个带有数据绑定属性的 SPAN 元素,该元素订阅了可观察到的 customProperty,如下所示:
<span data-bind="text: customProperty"
id="customProperty" style="font-weight:bold"></span>
到目前为止,还不错。以上工作正常,这意味着每当我在脚本中更改 customProperty 的值时,SPAN 中的文本会立即更新。例如,我可以成功且轻松地使用此表达式将可观察到的 customProperty 的值从 0 更改为 10:
vm.customProperty(10);
我的问题:
请注意,我在引用数据绑定属性中的 customProperty
值时没有使用括号。为什么不需要括号?
我发现使用括号也可以:
我理解为什么使用括号有效(因为我正在读取 Knockout 可观察对象的值)。但是为什么不需要括号呢?换句话说,为什么第 1 点中的数据绑定表达式会起作用?
最后,这个作业到底发生了什么?
var customProperty = ko.numericObservable(0);
customProperty
是否最终持有一个指向名为 customProperty()
的函数的指针?
当 ko 解析绑定时,它会检查表达式是否是可观察的,如您所知,它是一个函数。如果表达式是可观察的,ko 会自动解包值以显示它,但它也允许订阅和通知。
在这种情况下,当 ko 解析表达式时,它找到了一个值,而不是一个可观察值,因此,它也可以正确显示该值(值更改 > 视图更新)。但是,您将失去从视图到值的绑定(输入值更改 > 可观察对象未更新),因为它不是可观察对象。有关详细信息,请参阅下面的说明和代码段。
customProperty
是一个函数,特别是 ko.observable
,这意味着它支持订阅和通知,除了使用 ()
读取或设置值或 (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 setters and getters 的属性,因此语法永远不需要括号。带有 settes 和 getters 的属性像任何其他 属性 一样被读取和写入,但在幕后 setter 或 getter 中的代码运行,允许订阅和通知发生.
注意 2(因为评论中有问题)。你可以这样想:当 ko 解析一个绑定表达式时,它立即计算整个表达式并检查结果是否是可观察的。所以,当你有一个像这样的表达式时:customProperty == 10
,当 ko 计算它时,它发现它不是一个可观察的(而是一个布尔值)并且没有采取额外的步骤来获取值。结果将始终为假,因为 customProperty
是 function
,因此是 '!= 10'。如果将表达式更改为以下表达式:customProperty() == 10
自定义 属性 值将被 ()
展开,并且比较将按预期进行。顺便说一下,尽量不要在绑定表达式中包含代码:如果可能,最好在模型中使用 computed observables (better pure computeds。
注释 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)
或 ko.isObservable(vm.customProperty() == 10)
。在这两种情况下,您都会得到 false
,因为在这两种情况下表达式都是 bool
,而不是可观察的函数。 Ko 没有分解表达式并逐个检查它。这将是在第一个表达式中发现 customProperty
是可观察的并且应该展开的唯一方法。但是ko并没有那样做。
注 3:表达式,作为计算的可观察值,当在原始评估中使用可观察值 属性 时被重新评估并且它发生变化它的价值。请注意,如果在第一次评估中您只访问一个可观察对象 属性,即使代码包含对其他可观察对象的引用,也只会在访问的可观察对象更改其值时重新评估。其他 observables 的变化不会是 "observed"。典型情况是 if
依赖于不同的可观察对象,具体取决于执行的分支
我已经看到其他线程,但我仍然感到困惑,我想我在这里提出了一个不同的案例。
我正在使用显示模式 return 我的 HTML 文档的视图模型对象。因此,我有一个看起来像这样的视图模型对象:
var vm = function() {
var customProperty = ko.numbericObservable(0);
return {
customProperty: customProperty
};
} ();
由此,您可以看到 customProperty 被分配给初始值为 0 的 Knockout numeric observable。
在包含上述 JavaScript 的 HTML 文档中,我有一个带有数据绑定属性的 SPAN 元素,该元素订阅了可观察到的 customProperty,如下所示:
<span data-bind="text: customProperty"
id="customProperty" style="font-weight:bold"></span>
到目前为止,还不错。以上工作正常,这意味着每当我在脚本中更改 customProperty 的值时,SPAN 中的文本会立即更新。例如,我可以成功且轻松地使用此表达式将可观察到的 customProperty 的值从 0 更改为 10:
vm.customProperty(10);
我的问题:
请注意,我在引用数据绑定属性中的
customProperty
值时没有使用括号。为什么不需要括号?我发现使用括号也可以:
我理解为什么使用括号有效(因为我正在读取 Knockout 可观察对象的值)。但是为什么不需要括号呢?换句话说,为什么第 1 点中的数据绑定表达式会起作用?
最后,这个作业到底发生了什么?
var customProperty = ko.numericObservable(0);
customProperty
是否最终持有一个指向名为 customProperty()
的函数的指针?
当 ko 解析绑定时,它会检查表达式是否是可观察的,如您所知,它是一个函数。如果表达式是可观察的,ko 会自动解包值以显示它,但它也允许订阅和通知。
在这种情况下,当 ko 解析表达式时,它找到了一个值,而不是一个可观察值,因此,它也可以正确显示该值(值更改 > 视图更新)。但是,您将失去从视图到值的绑定(输入值更改 > 可观察对象未更新),因为它不是可观察对象。有关详细信息,请参阅下面的说明和代码段。
customProperty
是一个函数,特别是ko.observable
,这意味着它支持订阅和通知,除了使用()
读取或设置值或(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 setters and getters 的属性,因此语法永远不需要括号。带有 settes 和 getters 的属性像任何其他 属性 一样被读取和写入,但在幕后 setter 或 getter 中的代码运行,允许订阅和通知发生.
注意 2(因为评论中有问题)。你可以这样想:当 ko 解析一个绑定表达式时,它立即计算整个表达式并检查结果是否是可观察的。所以,当你有一个像这样的表达式时:customProperty == 10
,当 ko 计算它时,它发现它不是一个可观察的(而是一个布尔值)并且没有采取额外的步骤来获取值。结果将始终为假,因为 customProperty
是 function
,因此是 '!= 10'。如果将表达式更改为以下表达式:customProperty() == 10
自定义 属性 值将被 ()
展开,并且比较将按预期进行。顺便说一下,尽量不要在绑定表达式中包含代码:如果可能,最好在模型中使用 computed observables (better pure computeds。
注释 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)
或 ko.isObservable(vm.customProperty() == 10)
。在这两种情况下,您都会得到 false
,因为在这两种情况下表达式都是 bool
,而不是可观察的函数。 Ko 没有分解表达式并逐个检查它。这将是在第一个表达式中发现 customProperty
是可观察的并且应该展开的唯一方法。但是ko并没有那样做。
注 3:表达式,作为计算的可观察值,当在原始评估中使用可观察值 属性 时被重新评估并且它发生变化它的价值。请注意,如果在第一次评估中您只访问一个可观察对象 属性,即使代码包含对其他可观察对象的引用,也只会在访问的可观察对象更改其值时重新评估。其他 observables 的变化不会是 "observed"。典型情况是 if
依赖于不同的可观察对象,具体取决于执行的分支