0

我正在使用 ko.mapping 实用程序设置我的模型。

传入我的主要数据时,请考虑我的一个属性是一个数组。这个数组是一周中每 7 天一个对象,所以我知道这个集合不会改变也不会重新排列。我可以轻松地将这个数组生成为具有扁平属性的 JSON 对象的副本,或者作为具有观察或扁平属性的 observableArray,但我似乎无法通过映射实用程序创建一个混合了基本性质和观察性质。

我尝试了映射选项的各种排列,但看起来我仍然必须映射这个数组,而没有或只是咬住我不断的肛门冲动,让这个复杂的模型以我想要的方式准确映射我想要的方式映射它。

为了更好地显示问题:

var PrimaryViewModelMapping = {
    copy: ['KeyProperty', 'ArrayOfDays'],
    create: function(options) { return new PrimaryViewModel(options.data); }
}

这将在我的 PrimaryViewModel 实例中为我提供一个平面副本,而无需任何额外的努力......但如果不循环遍历 PrimaryViewModel 声明中的数组并做一些事情,就无法控制 ArrayOfDays 中的属性。

接着说:

var PrimaryViewModelMapping = {
    copy: ['KeyProperty'],
    observe: ['ArrayOfDays'],
    create: function(options) { return new PrimaryViewModel(options.data); }
}

这将很好地将我的 ArrayOfDays 打包为一个可观察的数组,同时保持它的所有“每个”属性都是扁平的。

下一次尝试如下:

var PrimaryViewModelMapping = {
    copy: ['KeyProperty'],
    'ArrayOfDays': {
        copy: ['Date'],
        observe: ['TotalDuration'],
        create: function(options) {
            return new DayArrayModel(options.data);
        }
    }
}

这将创建一个可观察的数组,并让我完全控制观察到的内容(TotalDuration)和未观察到的内容(KeyProperty)以及在我的对象 DayArrayModel 的声明中,以及我可能想做的任何其他事情......

但是 ArrayOfDays 仍然是一个可观察的数组。我不需要,也不需要它。

了解这里的主题是特定于映射插件的,我不想在 PrimaryViewModel 声明中创建循环来处理这个......我知道我可以做到。只是想知道我是否偶然发现了“功能请求”,或者我只是没有得到它。

谢谢。

4

2 回答 2

2

如果您坚持要防止 ArrayOfDays 成为常规数组,则可以使用该ko.utils.arrayMap方法。但是,您想要的内容与映射插件的功能完全相反,因此它会变得有点冗长。

问题是映射选项不允许您指定如何构造单个属性,您只能告诉插件包含或排除属性,或者如何在数组中生成元素。所以你的第一步不是直接生成主视图模型。相反,您可以这样做:

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

    var mappingOptions = {
        'exclude': ['ArrayOfDays']
    };

    // Map everything, except the array
    ko.mapping.fromJS(data, mappingOptions, self);

    // Do the array itself, but prevent it from becoming an *observable* array
    self.ArrayOfDays = ko.utils.arrayMap(data.ArrayOfDays, function(item) { return new DayViewModel(item); });
};

这做了几件事:

  1. 创建self以防止任何令人讨厌的this问题;
  2. 设置一个选项变量,告诉 KO 我们将自己处理数组。
  3. 映射数组之外的所有内容,在self.
  4. 自己处理数组。

这里的关键是ko.utils.arrayMap它将返回一个平面数组,而不是 observableArray。

这是一个小提琴来证明这一点

作为脚注,我不清楚你为什么想要这样的东西(也许是过早的优化?)。

于 2013-10-31T21:54:11.240 回答
0

我在 Knockout 中遇到了关于映射的话题。我确实爬过这堵墙,但我仍然感到困惑。从高级用例的角度来看,映射插件似乎只是混淆了数据与 Knockout 绑定的 viewModel 之间的连接。

我从http://www.coderenaissance.com/发现了下面的列表(并添加了评论),它似乎还有一个映射插件的另一种变体,似乎还没有引起太多关注。我确实喜欢创作者的洞察力,因为它与我自己的经历非常吻合......

  • 在大型视图模型上速度很慢,特别是在旧浏览器(IE7/8)和大型阵列上。(没什么大不了的……还)
  • 创建视图模型不是一步的过程......在调用映射之后,您必须进一步扩展视图模型。 (有时,对于小型存储模型,我不需要这样做,但是对于其他属性/功能,我需要继续遵循我们现有的模式。)
  • 它没有提供简单的方法来组织视图模型创建代码,这在较大的视图模型上成为一个问题。(我最大的烦恼之一......我真的希望使用映射选项的组合可以真正减少属性的重复)
  • 它不允许对视图模型的创建方式进行太多自定义,并且那里的自定义内容令人困惑且使用起来不直观。(视图模型的操作是绝对无法避免的。映射过程的时间/顺序并不总是像我希望的那样可预测。当你开始将映射级联在一起时真的会感到困惑。)

所以,我的第一个问题的妙语……或笑话,现在在我看来……是没有勺子。由于我的发现,我删除了使用 ko.mapping 作为我的架构初始化的尝试,并且只使用它来在我的 ko.applybindings 命令之前从视图中准备我的初始触发器。在这一点上,我使用 arrayMap 和 observable(array) 的组合来填充我的对象......就像我以前一样。现在,我已经了解了何时使用映射插件。

于 2013-11-05T19:45:39.007 回答