1

我需要<select />通过两个不同的 AJAX 调用来获取 a 的当前值和可用选项(由于几个原因,我无法对它们进行排队/链接)。

我不知道这是否重要,但读取当前值的调用在每次读取可用选项之前完成。

使用 Knockout 2.0.0 和 Knockout Mapping 2.0.3 我用 绑定了选择data-bind="options: values, value: valueComputed",但我发现 Knockout 正在删除/忽略第一个 AJAX 调用设置的值,直到获取可用选项的调用完成才能设置当前值。

它是否正确?是否可以告诉 Knockout “这是当前值,当可用选项可用时选择它”?

经过几次测试后,我想出了一个问题:我没有将普通的 observable 绑定到 select 的值,而是使用了计算的 observable,我截取了该值,并且如果新值未定义,则不更改底层的 observable。

我在做坏事吗?

一个 jsFiddle 示例:http: //jsfiddle.net/KeNUU/

我正在使用的 JavaScript 代码:

var viewModel = function () {
    var self = this;

    // The underlying observable where
    // the selected value is stored.
    self.value = ko.observable();

    // The observable bound to
    // the value of the drop down.
    self.values = ko.mapping.fromJS([]);

    // Use a computed observable to intercept the undefined
    // value placed by KnockOut when binding the drop down.
    self.valueComputed = ko.computed({
        "read": function () {
            return ko.utils.unwrapObservable(self.value);
        },
        "write": function (value) {
            // Update the underlying observable only when
            // there is a value, if it's undefined ignore it.
            if (value) {
                self.value(value);
            }
        }
    });

    // Simulate the AJAX request which fetches the actual value,
    // this request must complete before the second one.
    setTimeout(function () {
        self.valueComputed("b");
    }, 1000 * 1);

    // Simulate the AJAX request which fetches the available values,
    // this reqest must complete after the first one.
    setTimeout(function () {
        ko.mapping.fromJS(["a", "b", "c", "d"], {}, self.values);
    }, 1000 * 2);
};

$(document).ready(function () {
    ko.applyBindings(new viewModel());
});
4

1 回答 1

2

我认为您所做的事情不会给您带来问题,但是您正在规避 KO 的逻辑,以确保有价值的东西是您选项中的有效选择。此外,如果您使用optionsCaption提供空白选项,那么您将无法清除您的值。在您的情况下,这可能无关紧要。

我认为一个更简单的选择是将初始值缓存在不可观察的值中,然后value在列表返回时使用它来填充。如果列表在前,那么就没有初始值,它可以正常工作。

就像是:

setTimeout(function () {
    self.initialValue = "b";
    self.value("b");
}, 1000 * 1);

// Simulate the AJAX request which fetches the available values,
// this reqest must complete after the first one.
setTimeout(function () {
    ko.mapping.fromJS(["a", "b", "c", "d"], {}, self.values);
    if (self.initialValue) {
         self.value(self.initialValue);
         self.initialValue = null;
    }    
}, 1000 * 2);

http://jsfiddle.net/rniemeyer/gB3E5/

现在,您可以预先处理此问题,而无需(次要)开销来计算可观察到的拦截每个下拉列表的更改。

于 2012-03-05T18:25:44.527 回答