在有序列表中隔离反应性

时间:2013-10-18 17:17:18

标签: mongodb meteor reactive-programming

我有一个按特定顺序显示切片的模板:

<template name="container">
{{#each tiles}}{{>tile}}{{/each}}
</template>

现在容器是一个瓦片列表,它存储为mongodb中的数组。

由于我希望瓷砖的显示顺序与它在数组中的显示顺序相同,我使用的是以下帮手:

Template.container.tiles = function () {
        return _.map(this.tiles || [], function(tileId) {
              return _.extend({
                   container: this
              }, Tiles.findOne({_id: tileId}));
        }, this);
    };
};

问题是,我:

  • 当任何容器包含瓷砖更改时,不希望整个容器重新呈现。 (只有相关的磁贴应该无效)。

  • 插入新图块时,不希望整个容器重新渲染。渲染的瓷砖应简单地在相应位置附加或插入。

  • 当瓷砖的顺序发生变化时,不希望整个容器重新渲染。相反,当订单更改时,应重新排列表示图块的DOM对象,而不重新渲染图块本身。

通过上述方法,我将无法满足要求,因为每个切片数据都标记为整个容器的依赖关系(运行Tiles.findOne({_id: tileId})时),整个tile-id数组都是容器的一部分数据,如果更改,则整个容器模板无效。

我想我应该将容器的光标标记为非反应性。像这样:

Containers.findOne({_id: containerId}, {reactive:false});

但是我仍然需要找出这个容器何时更改它的tile数组。

类似

 Deps.autorun(function() {
    updateContainer(Containers.findOne({_id: containerId}));
 });

但我希望该容器模板具有高度可重用性。所以无论什么解决方案,它都不应该需要一些依赖的准备工作。

声明我在哪里运行该自动运行功能? (当然我不能那个助手那样做,对吗?)

这是正确的方法吗?

有没有人对如何解决这个问题有更好的想法?

提前致谢...

1 个答案:

答案 0 :(得分:1)

我通常解决此问题的方法是创建一个辅助Collection对象,并在适当的observer的帮助下填充它。在你的情况下,这可能是这样的:

// this one should be "global"
var tiles = new Meteor.Collection(null); // empty name

现在,根据当前容器,您可以使用相应的数据填充tiles集合。此外,您可能需要记住每个对象的索引:

Deps.autorun(function () {

    var containerId = ... // get it somehow, e.g. from Session dictionary
    var tilesIDs = Containers.findOne({_id:containerId}).tiles;

    tiles.remove({}); // this will be performed any time
                      // the current container changes

    Tiles.find({ _id : { $in : tilesIDs } }).observeChanges({
        added: function (id, fields) {
            tiles.insert(_.extend({
                _index : _.indexOf(tilesIDs, id),
                _id    : id,
            }, fields);
        },
        changed: ... // you'll also need to implement
        removed: ... // these to guys
    });

});

帮助代码现在非常简单:

Template.container.tiles = function () {
    return tiles.find({}, {sort : {_index : 1}});
}

修改

请注意,为了防止每次容器对象更改时重新呈现整个列表(例如,tile的顺序发生变化),您需要创建一个不依赖于的单独listOfTiles模板容器对象本身。