1

使用 Knockout.js:

如果一个项目/对象位于多个位置的视图模型中(相同的确切对象),是否可以将两个项目绑定在一起,以便如果用户在一个位置编辑项目,另一个项目会自动更新为出色地?

示例:http: //jsfiddle.net/77Jc5/1/

var model = {
    Foo : [
        {
            ID: 99,
            Title: 'This is item number ninety-nine',
            Description: 'This is an item included in more than one object'
        },
        {
            ID: 100,
            Title: 'This is item number one-hundred',
            Description: 'This is an item included in only one object'
        }
    ],
        Poo : [
        {
            ID: 99,
            Title: 'This is item number ninety-nine',
            Description: 'This is an item included in more than one object'
        }
    ]
};

在示例中,当用户在 Foo 或 Poo 中编辑 Item #99 时,我希望它在两者中都进行更改……最好是在用户更改它时(按键事件?)。

解决方案

您的模型应如下所示:

var model = {
    AllMembers: [
        { ID: 100, Title: 'This is item number 100' },
        { ID: 776, Title: 'This is item number 776' },
        { ID: 456, Title: 'This is item number 456' },
        { ID: 999, Title: 'This is item number 999' }
    ],
    Foo: [],
    Poo: []
};

解决方案 1:(感谢@Joseph Gabriel)

http://jsfiddle.net/lamarant/hMutz/8/

在此解决方案中,Foo 和 Poo 数组将包含对象的重复实例。Knockout 负责对象之间的同步。这可行,但从架构的角度来看,它并不理想,因为数据在整个视图模型中都是重复的。

解决方案 2:(感谢@Jeff Mercado)

http://jsfiddle.net/jeff1203/rndM9/2/

在这个解决方案中,Foo 和 Poo 数组将只包含被引用对象的 ID。在架构上,我认为这是正确的方法,但它也以更多代码为代价。

如果您正在阅读本文,那么最终您可能会将视图模型发布到服务器进行处理,这可能需要将模型保存回您的数据库。这两种解决方案都能充分处理数据库中存在的一对多关系。在我的要求中,我还使用顺序负数作为 ID 号(ID:-1、ID:-2 等)向 AllMembers 数组添加新元素。服务器端处理顺序应如下所示:

  1. 创建一个数组以将负 ID 映射到数据库中相应的数据库新创建的 ID
  2. 循环遍历 AllMembers 数组中的成员并更新/创建数据库中的每个成员。如果创建新成员,请将其负数和新 ID 添加到您在步骤 1 中创建的数组中。
  3. 删除数据库中 Foo/Poo 之间所有现有的 1 对多关系,因为您的模型现在是该信息的主人
  4. 循环遍历 Poo 和 Foo,并将模型中到 Foo/Poo 的所有关系添加到 1-many 表中(使用 ID)

呼...

淘汰赛很棒。

4

4 回答 4

2

要记住的主要事情是,淘汰赛将更新它绑定到的任何对象,但是为了使同一个对象可更新并反映多个位置的更改,它确实必须是同一个对象,而不仅仅是一个克隆

两个具有相同名称和/或属性的对象是不够的。它实际上必须是一个对象,指向同一个内存地址,然后可以在多个位置显示和绑定。

我会考虑将您的数据从您的 viewModel 中分离出来,以便您可以根据需要从尽可能多的地方引用相同的项目。

var items = [{
    ID: 99,
    Title: 'This is item number ninety-nine',
    Description: 'This is an item included in more than one object'
}, {
    ID: 100,
    Title: 'This is item number one-hundred',
    Description: 'This is an item included in only one object'
}];

var model = {
    Foo : [
        items[0],
        items[1]
    ],
        Poo : [
        items[0]
    ]
};
var viewModel = ko.mapping.fromJS(model);
ko.applyBindings(viewModel);

也就是说,在您的视图模型中直接有重复引用似乎有点尴尬。我不知道您的情况是什么,但是可以使用Ko吗?计算给你“便便”值,反之亦然?

于 2013-04-22T02:16:18.843 回答
1

理想情况下,同一视图模型中的任何对象最多只能有一个副本。如果你能帮助它,重构你的视图模型,这样你的对象可以引用一个包含所有对象的数组/映射来最小化复制。然后你的实际对象只需要获取引用的对象。

var model = {
    _FooRefs: [99, 100],
    _PooRefs: [99],
    _AllObjects: [
        {
            ID: 99,
            Title: 'This is item number ninety-nine',
            Description: 'This is an item included in more than one object'
        },
        {
            ID: 100,
            Title: 'This is item number one-hundred',
            Description: 'This is an item included in only one object'
        }
    ]
};
function ViewModel(data) {
    var self = this;
    ko.mapping.fromJS(data, {
        _AllObjects: {
            key: function (obj) {
                return obj.ID;
            }
        }
    }, self);

    self.Foo = ko.computed(function () {
        var fooRefs = ko.utils.unwrapObservable(self._FooRefs);
        return ko.utils.arrayMap(fooRefs, function (id) {
            // mappedGet was added to mapping plugin version 2.4.1
            return self._AllObjects.mappedGet({ ID: id });
        });
    });

    self.Poo = ko.computed(function () {
        var pooRefs = ko.utils.unwrapObservable(self._PooRefs);
        return ko.utils.arrayMap(pooRefs, function (id) {
            return self._AllObjects.mappedGet({ ID: id });
        });
    });
}

小提琴

要将对象添加到数组中,您需要确保该对象存在于您的数组/映射中,然后将对象的键添加到引用数组中。要删除项目,请删除引用并可选择删除对象。


如果这样做不是一个选项,并且您需要保持重复,您可以使用邮箱插件来帮助保持对象同步。如果对象存在于单独的视图模型中,这种方法将是最好的。

于 2013-04-23T03:02:16.210 回答
0

架构的角度来看,我相信你不应该像这样复制你的模型。而是只使用 'Foo' 并在多个视图上使用它。你有更少的代码重复,一切都是自动发生的,而且更不容易出错。

为此,您可以ko.applyBindings()在多个元素上使用该函数。

这里也有按键事件的小例子:http: //jsfiddle.net/Z5yGf/2/

于 2013-04-22T01:01:47.240 回答
0

如果你写这样的代码:

var num99 = {
            ID: 99,
            Title: 'This is item number ninety-nine',
            Description: 'This is an item included in more than one object'
        };

var model = {
    Foo : [
        num99,
        {
            ID: 100,
            Title: 'This is item number one-hundred',
            Description: 'This is an item included in only one object'
        }
    ],
        Poo : [
        num99
    ]
};

然后FooPoo确实,指向同一个对象,所以改变一个会改变另一个。

jsFiddle 示例

于 2013-04-22T00:59:10.500 回答