何时使用或不在数据绑定表达式

时间:2015-12-15 23:45:42

标签: javascript knockout.js data-binding javascript-databinding

我已经看到了其他线索,但我仍然感到困惑,我想我在这里提出了一个不同的案例。

我正在使用显示模式将视图模型对象返回到我的HTML文档。因此,我有一个看起来像这样的视图模型对象:

var vm = function() {
   var customProperty = ko.numbericObservable(0);

   return {
      customProperty: customProperty
   };
} ();

从这里可以看出,customProperty被分配给一个初始值为0的Knockout数字observable。

在包含上述JavaScript的HTML文档中,我有一个带有data-bind属性的SPAN元素,该属性可以订阅customProperty observable,如下所示:

<span data-bind="text: customProperty" 
  id="customProperty" style="font-weight:bold"></span>

到目前为止,这么好。上面的工作正常,这意味着每当我在脚本中更改customProperty的值时,SPAN中的文本立即更新。例如,我可以成功轻松地使用此表达式将customProperty observable的值从0更改为10:

vm.customProperty(10);

我的问题:

  1. 请注意,在引用data-bind属性中的customProperty值时,我没有使用括号。为什么不需要括号?

  2. 我发现使用括号也有效:

  3. 我理解为什么使用括号可以工作(因为我正在读取Knockout observable的值)。但为什么括号不需要呢?换句话说,为什么第1点的数据绑定表达式会起作用?

    1. 最后,这项任务实际发生了什么?

      var customProperty = ko.numericObservable(0);

    2. customProperty最终是否持有指向名为customProperty()的函数的指针?

1 个答案:

答案 0 :(得分:6)

  1. 当ko解析绑定时,它会检查表达式是否是一个observable,正如你所知道的那样是一个函数。如果表达式是可观察的,ko会自动展开值以显示它,但它也允许订阅和通知。

  2. 在这种情况下,当ko解析表达式时,它会找到一个值,而不是一个可观察的值,因此,它也可以正常显示值(值更改&gt;查看更新)。但是,您将失去从视图到值的绑定(输入值更改&gt; observable不会更新),因为它不是可观察的。有关详细信息,请参阅下面的说明和摘要。

  3. customProperty是一个函数,特别是ko.observable,这意味着支持订阅和通知,除了使用()或{{1读取或设置值语法

  4. 注意:使用和不使用括号之间的区别很大。如果你这样做:

    (newValue)

    正如我在1中解释的那样,ko发现<input type="text" data-bind="value: customProperty" ... 是一个可观察的,所以当用户更改customProperty中的值时,新值将被写回observable。如果你这样做:

    input

    正如我在2中解释的那样,ko找到了一个值,而不是一个可观察的值。因此,如果用户通过在其上键入来更改<input type="text" data-bind="value: customProperty()" ... 的值,则新值不会反馈给observable,因为ko不知道它是可观察的。 (但是如果更新了可观察值,则视图会更改,因为在表达式求值期间会发现并订阅依赖项。)

    &#13;
    &#13;
    input
    &#13;
    var vm = {
    	customProperty: ko.observable(10)
    };
    
    ko.applyBindings(vm);
    &#13;
    body {
      font-family: Segoe, Arial
    }
    &#13;
    &#13;
    &#13;

    在其他框架中,比如Angular,它使用JavaScript settersgetters的属性,而不是使用函数,因此语法永远不需要括号。具有settes和getter的属性被读取和写入任何其他属性,但是在幕后,setter或getter中的代码运行,允许订阅和通知发生。

    注2(由于评论中的问题)。您可以这样想:当ko解析绑定表达式时,它会立即计算整个表达式并检查结果是否是可观察的。所以,当你有一个这样的表达式:<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"/>时,当ko计算它时,它发现它不是一个可观察的(但是一个布尔值)并且不需要额外的步骤来获取值。结果将始终为false,因为customProperty == 10customProperty,因此是&#39;!= 10&#39;。如果您将表达式更改为此表达式:function自定义属性值将由customProperty() == 10解包,并且比较将按预期工作。顺便说一下,尽量不要在绑定表达式中包含代码:在模型中使用computed observables(如果可能的话,更好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)。这就是ko的作用。所以知道它必须解开价值。输入true,您就会看到ko.unwrap(vm.customProperty)

    最后,输入10ko.isObservable(vm.customProperty == 10)。在这两种情况下,您都会获得ko.isObservable(vm.customProperty() == 10),因为在两种情况下表达式都是false,而不是可观察的函数。 Ko没有解析表达并逐个检查。这将是在第一个表达式中发现bool是一个可观察的并且应该被解包的唯一方法。但是ko并没有这样做。

    注3:当在原始评估中使用可观察属性时,表达式(如计算的可观察量)会重新评估,并且会更改其值。请注意,如果在第一次评估中您只访问可观察属性,即使代码包含对其他可观察对象的引用,也只有在被访问的observable更改其值时才会重新评估它。其他观察者的变化不会被观察到&#34;。典型情况是customProperty取决于执行的分支取决于不同的可观察量