1

我有一个以特定顺序显示图块的模板:

<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);
    };
};

问题是,我:

  • 不希望整个容器在其包含的任何瓦片发生更改时重新渲染。(只有相关的图块应该无效)。

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

  • 当图块的顺序改变时,不希望整个容器重新渲染。相反,当顺序发生变化时,应该重新排列代表 tile 的 DOM 对象,而无需重新渲染 tile 本身。

使用上述方法,我将无法满足要求,因为每个图块数据都被标记为Tiles.findOne({_id: tileId})整个容器的依赖项(运行时),并且整个 tile-ids 数组是容器数据的一部分,如果这会改变整个容器模板无效。

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

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

但我仍然需要找出这个容器何时改变它的瓷砖数组。

所以像

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

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

在哪里声明我运行该自动运行功能?(当然我不能在那个助手中做到这一点,对吧?)

这是正确的方法吗?

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

提前致谢...

4

1 回答 1

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}});
}

编辑:

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

于 2013-10-18T20:05:59.360 回答