javascript - 计算的可观察量不会收到更改通知

标签 javascript knockout.js ko.observablearray computed-observable

接下来的所有代码都可以在 JSFiddle 中看到。 。我在这个问题中省略了 HTML 数据绑定(bind)和模板,但它们可以在 fiddle 中看到。我认为它们与说明问题无关。

<小时/>

简介

我正在尝试将计算的可观察量链接到我用作 HashMap 的另一个对象。

具有计算的可观察量的对象是 HistoryEntry:

function HistoryEntry(userId, users) {
    this.UserId = ko.observable(userId);

    this.User = ko.computed(function () {
        if (!users[this.UserId()]) return '(' + this.UserId() + ')';
        return '(' + this.UserId() + ') ' + users[this.UserId()].Name();
    }, this);
}

HistoryEntry 包含一个 UserId,它充当我的 JavaScript 对象(充当 HashMap)中的查找值。 users 是对 ViewModel 中包含的此 HashMap 的引用。

HashMap 包含由 UserId 键控的 User 对象。 User 对象如下:

function User(id, name) {
    this.Id = ko.observable(id);
    this.Name = ko.observable(name);
}

这个想法是,计算出的可观察对象 HistoryEntry.User() 将从该 HashMap 中相应的 User 对象中查找名称。

HashMap 与 HistoryEntry 对象的可观察数组一起存储在父 ViewModel 上:

function ViewModel() {
    this.users = ko.observable({
        '16': new User(16, 'Jack'),
        '17': new User(17, 'Jill')
    });

    this.history = ko.observableArray([
        new HistoryEntry(16, this.users()),
        new HistoryEntry(17, this.users()),
        new HistoryEntry(18, this.users())
    ]);
}

var view = new ViewModel();
ko.applyBindings(view);

问题

正如您在上面看到的,我只创建了两个用户,但我有三个历史条目,每个条目都指向不同的用户。这些条目之一引用了 HashMap 中尚不存在的 User(18)。

对于我的示例,我将 User(16) 的名称从“Jack”更改为“John”并添加 User(18):

setTimeout(function () {
    view.users()[16].Name('John');
    view.users()[18] = new User(18, 'Bill');
    view.users.valueHasMutated();
    view.history.valueHasMutated();
}, 1000);

这会正确更新具有指向 User(16) 的计算可观察量的 HistoryEntry

同样,我预计当我添加 User(18) 时,带有 User(18) 的计算可观察值的 HistoryEntry 将使用 User(18) 的名称进行更新。

不幸的是,事实并非如此。

问题

  1. 我想更深入地了解既然 User(18) 确实存在,为什么指向 User(18) 的 HistoryEntry 没有收到更改通知。
  2. 此外,我需要找到一个解决方案,当将 User(18) 添加到用户 HashMap 时,该解决方案将更新指向 User(18) 的 HistoryEntry

最佳答案

HistoryEntry 不会更新,因为您没有在计算中解开用户

尝试改变

new HistoryEntry(18, this.users())

new HistoryEntry(16, this.users)

然后将 HistoryEntry 更改为:

function HistoryEntry(userId, users) {
    this.UserId = ko.observable(userId);

    this.User = ko.computed(function () {
        var usersArr = ko.unwrap(users);
        if (!usersArr[this.UserId()]) return '(' + this.UserId() + ')';
        return '(' + this.UserId() + ') ' + usersArr[this.UserId()].Name();
    }, this);
}

参见http://jsfiddle.net/W6nRe/

计算会跟踪计算中使用的所有可观察量,因为您使用的是底层用户对象,所以它没有对用户的引用。因此,只有当它使用的可观察量之一发生更改时,计算值才会更新。

关于javascript - 计算的可观察量不会收到更改通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21163800/

相关文章:

javascript - javascript 警报中的空格?

javascript - 奇怪的数据绑定(bind)问题

javascript - 无法正确绑定(bind) observables 的 observableArray

knockout.js - Hasfocus 与 Firefox 的绑定(bind)问题

javascript - 操作 DOM 时的数据绑定(bind)不适用于 Angular、Knockout

javascript - knockout : How can I pass a single item from an observable array into my viewmodel?

javascript - Gmail 存在身份验证问题。某些功能可能无法使用

javascript - 如何使用 javascript 将新属性动态插入到 xml 标记中?

javascript - CSS 将文本置于图像之上

jquery - Knockout JS 并传入一个已经存在的数组