2

我正在尝试使用 ko.validation 验证列表中的条目与列表中的所有其他条目是唯一的,但是我在不应该运行验证时遇到了问题。

我有一个可编辑的列表 (a ko.observableArray),并且该数组中的每个项目都是一个带有 a 的视图模型ko.observable

var vm = function (data) {
    var self = this;

    self.items = ko.observableArray();

    _.each(data.words, function (word) {
        self.items.push(new listItemVm({parent: self, word: word.word}));
    });
};

var listItemVm = function (data) {
    var self = this;
    self.parent = data.parent;
    self.word = ko.observable(data.word);
};

然后我向listItemVm.wordko.observable 添加了一些验证。我希望每一个都是独一无二的:

var listItemVm = function (data) {
    var self = this;
    self.parent = data.parent;
    self.word = ko.observable(data.word).extend({
        validation: {
            validator: function (name, params) {
                console.log("validating " + name);
                // word we are editing must be different from all other words

                // uncommenting this next line causes the behaviour
                // I would expect because params.parent.items() 
                // is not called
                //return true;

                var allWords = params.parent.items();

                // exclude current view model we are editing
                var otherWordViewModels = _.filter(allWords, function (row) {
                    return row !== params.currentRow;
                });

                var otherWords = _.map(otherWordViewModels, function (item) {
                    return item.word();
                });

                return !_.contains(otherWords, name);
            },
            message: 'Must be unique',
            params: {
                currentRow: self,
                parent: self.parent
            }
        }
    });
};

我给它一些数据,并将其包装在一些 HTML 中:http: //jsfiddle.net/9kw75/3/

现在,这确实有效- 验证正确运行并在两个输入的值相等时显示无效 - 但请查看该小提琴的控制台。为什么验证例程在加载时运行三五次,为什么只有一个值更新时两个字段都验证?

  • 页面加载时
    • 预期:验证对每个输入字段运行一次。
    • 实际:一个输入验证运行 3 次,另一个输入运行 2 次。
  • 值更新时(任一输入字段)
    • 预期:仅对更改的输入字段运行验证
    • 实际:两个输入字段的验证运行

值得注意的是,这种奇怪的行为只有在阅读params.parent.items()验证器后才会观察到。如果 return 被注释掉,我期望的行为就会被观察到。

4

1 回答 1

2

我相信它的工作方式是在计算的 observable 中使用“验证器”函数。因此,任何在执行时读取的 observables 现在都是计算的依赖项。由于您word在此函数中读取每个项目的可观察项,因此每个项目都会触发所有其他项目的验证。

它以这种方式工作是有道理的,尽管在您的特定应用程序的情况下,它没有意义。您可以peek在不触发依赖检测的情况下读取 observables:

var allWords = params.parent.items.peek();

// ...

var otherWords = _.map(otherWordViewModels, function (item) {
    return item.word.peek();
});
于 2013-10-18T00:24:36.103 回答