【问题标题】:How Knockout JS Declarative Binding internally worksKnockout JS 声明式绑定如何在内部工作
【发布时间】:2016-05-31 04:34:40
【问题描述】:

我编写了一个代码,通过单击按钮显示或隐藏特定的 div。代码在this fiddle。 代码工作正常,但我怀疑当我在单击按钮时更改可观察到的ab 的值时,怎么会调用toShow 方法?

每当我的“testViewModel”发生变化时,它会被调用吗? 另外我什么时候必须在data-bind 中使用()

HTML 代码:

<button data-bind="click: $root.changeValue">Click Me!</button>
 <div data-bind="foreach: products">
   <div data-bind="visible: $root.toShow()">
     <div data-bind="text: name"></div>
     <div data-bind="text: age"></div>
     <div data-bind="text: gender"></div>
   </div>
</div>

Javascript 代码:

function testViewModel(){
   var self = this;
   self.a = ko.observable(0);
   self.b = ko.observable(0);
   var prod = [];
   for(var item in products){
     prod.push(new productItem(products[item]));
   }
   self.products = ko.observableArray(prod);
   self.changeValue = function(){
     self.a(self.a()+1);
     self.b(self.b()+1);
   }
   self.toShow = function(){
    if(self.a() % 2 === 0){
      return true;
    }
    else{
      return false;
    }
   }
 }

 function productItem(product){
   var self = this;
   self.name = ko.observable(product.name);
   self.age = ko.observable(product.age);
   self.gender = ko.observable(product.gender);
 }

 var products = [
 {
   name: 'A',
   age: 25,
   gender: 'Male'
 },
 {
   name: 'B',
   age: 27,
   gender: 'Female'
 },
 {
   name: 'C',
   age: 53,
   gender: 'Female'
 },
 {
   name: 'D',
   age: 54,
   gender: 'Male'
 }
]

ko.applyBindings(new testViewModel());

【问题讨论】:

    标签: javascript knockout.js data-binding


    【解决方案1】:

    第一个问题,意译:

     <div data-bind="visible: $root.toShow()">...</div>
    
     self.a = ko.observable(0);
     self.b = ko.observable(0);
     self.toShow = function(){
      if(self.a() % 2 === 0){
        return true;
      }
      else{
        return false;
      }
     }
    

    ...当我在按钮单击时更改可观察到的ab 的值,那么toShow 方法是如何被调用的?

    只要您的视图中有任何有效的数据绑定表达式,Knockout 将在第一次评估时注册一个依赖树以跟踪哪个observable(包括可观察数组等)影响数据绑定表达式。它这样做是为了绑定到普通的 observables,但也适用于你拥有的函数。

    这意味着data-bind="visible: $root.toShow() 将使 Knockout 在第一次评估时看到它依赖于 a(但 依赖于 b!),并且每当 a 更改时,它都会重新- 评估 visible 绑定。

    第二个问题

    ...我什么时候必须在数据绑定中使用()

    这已经是asked before,尽管目前恕我直言,答案还不是很完整。知道这两件事:

    1. observable 是一个函数,不带参数调用它获取它的当前值。
    2. 如果 Knockout 将可观察的名称视为数据绑定表达式中的唯一内容,它将“神奇地”添加这些括号。

    因此,在数据绑定中执行myObservable()始终安全且可选的,并且您可以有时(例如,当可观察名称是表达式)去掉括号。

    附言

    您的问题标题询问“它在内部是如何工作的”,因此请注意 Knockout 是 open source,您可以自己查看 e.g. the expression rewriting

    【讨论】:

      【解决方案2】:

      在您的示例中,toShow 只会在视图被渲染时触发一次。要进行淘汰赛以跟踪依赖项,您必须将其作为计算

      <code>
      self.toShow = ko.computed(function(){
          var x = self.a();
          if(x % 2 === 0){
            return true;
          }
          else{
            return false;
          }
      });
      </code>
      

      请注意,我在 if 语句之前得到了 observable a 的值 - 这是为了确保淘汰赛始终在此计算中跟踪此依赖关系。因为在您的示例中,如果它转到 else 分支,将不再依赖于 a.

      至于第二个问题:计算和观察不需要括号。简单的功能必须要有。

      【讨论】:

        猜你喜欢
        • 2019-12-05
        • 2018-10-19
        • 1970-01-01
        • 2015-09-18
        • 2012-03-19
        • 1970-01-01
        • 1970-01-01
        • 2012-12-30
        • 2019-01-23
        相关资源
        最近更新 更多