【问题标题】:Knockout doesn't seem to like object.property in bind淘汰赛似乎不喜欢绑定中的 object.property
【发布时间】:2015-07-25 01:42:53
【问题描述】:

在我的 Knockout.js 模板中,如果我可以访问视图模型上对象的属性会很方便:

<span data-bind="text: account.shortName"></span>

这不起作用。该元素为空白。但是,我可以这样做:

<div data-bind="with: account">
  <span data-bind="text: shortName"></span>
</div>

有没有办法解决这个问题? with一定要到处都用吗,多余的元素也要用吗?

【问题讨论】:

  • account 对象必须是可观察的吗?如果它必须是可观察的,那么您必须使用with 绑定或通过计算的可观察对象访问。
  • @JeffMercado 有趣。是的,就我而言,它必须是可观察的。谢谢(你的)信息。您可以将其发布为答案以便我接受吗?
  • 如果account 是可观察的,请尝试text: account().shortName
  • @JohnnyHK:这样做会导致各种问题,尤其是如果shortName 是可观察到的。
  • @JohnnyHK 那行不通。 “无法处理绑定......无法读取未定义的属性'shortName'”我认为这是因为在某些时候,帐户在我的应用程序中未定义。

标签: knockout.js knockout-3.0


【解决方案1】:

如果account 是可观察的,那么您真的应该像已经拥有它一样使用with 绑定,或者使用计算的可观察对象来访问该属性。当然,这有点冗长,但必须这样做。

使用像someObservable().someProperty 这样的表达式只会导致头痛和困惑,应该避免。例如,如果您确实使用了它并且 someProperty 恰好是可观察到的,那么当 someObservable 更改时,您可能会注意到有些地方不对劲。绑定将不会更新为使用新值的someProperty,希望您能明白原因。

您可以通过创建一个函数来更轻松地以安全的方式创建计算的 observable。

ko.observable.fn.property = function (name) {
    return ko.computed({
        read: function () {
            var parentValue = this();
            if (parentValue)
                return ko.utils.unwrapObservable(parentValue[name]);
        },
        write: function (value) {
            var parentValue = this(), property;
            if (parentValue) {
                property = parentValue[name];
                if (ko.isWriteableObservable(property))
                    property(value);
            }
        },
        owner: this
    });
};

然后你可以在你的绑定中使用它:

<span data-bind="text: account.property('shortName')"></span>

【讨论】:

  • 你确定吗? someObservable().someProperty 效果很好。如果我没记错的话,我已经做了很多次了。 ko 足够聪明,可以同时跟踪当前对象引用和当前引用中的 observable 的变化。因此,如果将 someObservable 完全更改为另一个对象,则绑定更新为新对象的子可观察对象。
  • 现在,据我了解,它运作良好。无论是以前版本的淘汰赛还是我正在研究的一个非常具体的案例,我都被烧死了,因为淘汰赛似乎没有重新绑定输入。所以很长一段时间以来,我都试图保证它的安全,并且总是推荐这种方法。我对此的立场已经改变。
  • 我不是堆栈溢出方面的专家,但你不能编辑答案来纠正(删除)这个错误的评估吗?一旦答案被接受就不可能了吗?
【解决方案2】:

Jeff 的回答很好,但您也可以通过将绑定更改为:

text: account() && account().shortName

我发现与 Jeff 在他的回答中提到的相反,即使 shortName 是可观察的,因为绑定是 implemented inside of a computed observable,这仍然有效。换句话说,text 绑定的值被实现为一种匿名计算。

这里有一个 sn-p 表明它可以工作,从没有值的 account observable 开始,然后随着时间的推移更新。

var vm = {
  account: ko.observable()
};

$(function() {
  ko.applyBindings(vm);

  // After a second, set account
  setTimeout(function() {
    var account = {
      shortName: ko.observable('Initial account')
    };
    vm.account(account);

    var newAccount = {
      shortName: ko.observable('New account')
    }

    // After another second, change account
    setTimeout(function() {
      vm.account(newAccount);

      // After another second, change shortName within the new account
      setTimeout(function() {
        newAccount.shortName('New shortName value in the new account');
      }, 1000);
    }, 1000);
  }, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<body>
  <h1>Account Binding Test</h1>
  <span data-bind="text: account() && account().shortName"></span>
</body>

【讨论】:

  • 我想我说的很多话都是因为在早期版本的淘汰赛中被它咬了。现在看起来这不是当前版本的问题。根据我过去观察到的情况,如果将表达式评估为可观察对象,则当父可观察对象更改时绑定不会更改,dom 元素将保持绑定到该可观察对象。它不是作为计算出来的。也许我正在查看的示例要复杂得多,并且是由其他问题引起的。
猜你喜欢
  • 2013-02-04
  • 1970-01-01
  • 2023-03-13
  • 2013-10-31
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多