我有一个按特定顺序显示切片的模板:
<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}));
});
但我希望该容器模板具有高度可重用性。所以无论什么解决方案,它都不应该需要一些依赖的准备工作。
声明我在哪里运行该自动运行功能? (当然我不能那个助手那样做,对吗?)
这是正确的方法吗?
有没有人对如何解决这个问题有更好的想法?
提前致谢...
答案 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
模板容器对象本身。