【问题标题】:Why does a function behave like a computed?为什么函数的行为类似于计算函数?
【发布时间】:2013-09-18 09:59:20
【问题描述】:

鉴于以下 HTML/JS (http://jsfiddle.net/mgs_jsfiddle/gUhm2/)

<div data-bind="foreach: users">
    <p data-bind="click: $root.onClick">
        <span data-bind="text: id"></span>
        <span data-bind="text: firstName"></span>
        <span data-bind="text: $root.isSelected($data)"></span>
    </p>
</div>

$(function() {
    function ViewModel() {
        var self = this;
        self.users = [
            { id: 1, firstName: "Bob" },
            { id: 2, firstName: "David" },
            { id: 3, firstName: "Walter" }
            ];
        self.selectedId = ko.observable(1);
        self.isSelected = function(user) {
            return user.id === self.selectedId() ? "YES" : "NO";
        };
        self.onClick = function(user) {
            self.selectedId(user.id);
        }
    };
    ko.applyBindings(new ViewModel());
});

显示一个列表。通过单击一行,该行的 id 将存储到selectedId

我不明白,为什么在更改selectedId 时重新评估函数isSelected。毕竟,这不是计算出来的。为什么还要重新评估?

【问题讨论】:

    标签: javascript knockout.js computed-observable


    【解决方案1】:

    Knockout 使用计算的 observable 来更新绑定。是这样的(修改自bindingAttributeSyntax.js):

    ko.computed({
        read: function() {
            bindingHandler.update(node, getValueAccessor(bindingKey), allBindings,
                bindingContext.$data, bindingContext);
        },
        disposeWhenNodeIsRemoved: node
    });
    

    因此,您访问以获取绑定值的任何 observable 都将成为此计算 observable 的依赖项并导致绑定更新。

    【讨论】:

      【解决方案2】:

      这是因为isSelected() 方法访问了selectedId 属性(即observable)。考虑一下:

      HTML

      <!-- adding into the foreach: block  -->
      <span data-bind="text: $root.someFunc()"></span>
      <span data-bind="text: $root.someOtherFunc()"></span>
      

      JS

      // adding to a model definition
      self.someFunc = function() {
          self.selectedId();
          console.log('I AM AN OBSERVER');
          return 'oi: ' + Math.random();
      };
      self.someOtherFunc = function() {
          // self.selectedId();
          console.log('AND I AM NOT');
          return 'no: ' + Math.random();
      }
      

      Fiddle.

      如您所见,这些函数之间的唯一区别是第一个函数确实检查定义为ko.observable 的模型属性的值。所以每次self.selectedId 改变时,都会通知这个函数(这实际上意味着它会重新运行)。

      请注意,如果您删除相应的data-bind 部分,此方法将不会在视图初始化阶段运行,因此无法注册为适当的观察者。

      第二种方法虽然也在初始化阶段被调用,但不会尝试检查 selectedId 值 - 所以它没有注册为这个值的观察者,并且随后也没有被调用。

      【讨论】:

      • 我明白。但是,在阅读文档后,我不会这么认为。那么,如果访问基本 observables 的普通函数做同样的事情,那么计算 observables 的原因是什么?查看knockoutjs.com/documentation/computedObservables.htmlfullName 被编码为计算值。如果将其编码为普通函数,结果会不会相同?
      • 现在这个问题是already answered。 )
      • Knockout 的行为方式很好。因此可以编写一个对当前行中的数据进行操作的全局函数。函数也可以写成计算的吗?我不知道如何将 $data 移交给计算。
      猜你喜欢
      • 1970-01-01
      • 2015-05-21
      • 2014-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多