将反应性隔离在有序列表中 [英] Isolate reactivity in an ordered list

查看:86
本文介绍了将反应性隔离在有序列表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have got a template that shows tiles in a particular order:

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

现在,容器是一列切片,这些切片作为数组存储在mongodb中.

Now the container is a list of tiles that is stored as an array in mongodb.

由于我希望以与在该数组中显示的顺序相同的顺序显示图块,因此我使用以下帮助程序:

Since I want the tiles to be shown in the same order as they appear in that array, I'm using the following helper:

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

问题是,我:

  • 当其中任何一个包含图块发生更改时,不希望整个容器重新呈现. (只有relevent磁贴应该无效).

  • Do not want the entire container to rerender when the any of it's contain tiles changes. (Only the relevent tile should be invalidated).

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

Do not want the entire container to rerender when a new tile is inserted. The rendered tile should be simply appended or insteted at the respective location.

更改瓦片的顺序时,不希望重新渲染整个容器.相反,当顺序更改时,应该重新排列代表图块的DOM对象,而不必重新呈现图块本身.

Do not want the entire container to rerender when the order of the tiles is changed. Instead, when the order changes, the DOM objects that represent the tile should be rearranged without re-rendering the tile itself.

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

With the above approach I will not meet the requirements, because the each tiles data is marked as a dependency (when running Tiles.findOne({_id: tileId})) of the entire container and the entire array of tile-ids is part of the containers data and if that changes the entire container template is invalidated.

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

I'm thinking I should mark the cursor for the container as non-reactive. Something like this:

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

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

But I still need to find out when this container changes it's tiles array.

类似

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

但是我希望该容器模板具有高度可重用性.因此,无论那里有什么解决方案,都不需要做任何准备工作就具有依赖性.

But I want that container template to be highly reusable. So whatever solution there it should not require some preparations with dependencies.

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

Where do declare I run that autorun function? (surely i cannot do that in that helper, right?)

这是正确的方法吗?

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

Does anybody have better ideas on how to solve this problem?

预先感谢...

推荐答案

我通常解决此问题的方法是创建一个辅助Collection对象,并在适当的observer的帮助下进行填充.在您的情况下,可能类似于:

The way I usually approach this problem is by creating an auxiliary Collection object and populate it with a help of appropriate observer. In your case this might be something like:

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

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

Now, depending on the current container, you can populate the tiles collection with corresponding data. Also, you'll probably need to remember each object's index:

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

});

辅助代码现在非常简单:

The helper code is now really simple:

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

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

Please note, that in order to prevent the whole list being rerendered every time the container object changes (e.g. the order of tiles changes), you'll need to make a separate listOfTiles template that does not depend on the container object itself.

这篇关于将反应性隔离在有序列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆