2013-10-18 5 views
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); 
    }; 
}; 

Проблема заключается в том, что я:

  • Не хотите, чтобы весь контейнер переигрывал, когда какая-либо из них содержит плитки. (Только подходящая плитка должна быть недействительной).

  • Не хотите, чтобы весь контейнер перестал появляться при вставке новой плитки. Выделенная плитка должна быть просто добавлена ​​или установлена ​​в соответствующем месте.

  • Не нужно, чтобы весь контейнер переходил на новый порядок при изменении порядка плиток. Вместо этого, когда порядок изменяется, объекты DOM, которые представляют фрагмент, должны быть перегруппированы без повторной обработки самого фрагмента.

С учетом указанных выше подхода не будет отвечать требованиям, потому что каждые данные плитки отмечен как зависимость (при запуске Tiles.findOne({_id: tileId})) всего контейнера, и весь массив плитки идентификаторами является частью контейнеров данные, и если это изменяет весь шаблон контейнера, он будет признан недействительным.

Я думаю, что я должен пометить курсор для контейнера как нереактивный. Что-то вроде этого:

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

Но мне все еще нужно выяснить, когда этот контейнер меняет массив плиток.

Так что-то вроде

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

Но я хочу, чтобы шаблон контейнера быть легко повторно. Так что любое решение там не должно требовать некоторых приготовлений с зависимостями.

Где объявить, что я запускаю эту функцию автозапуска? (конечно, я не могу это сделать в этом помощнике, верно?)

Правильно ли это?

У кого-нибудь есть лучшие идеи о том, как решить эту проблему?

Заранее спасибо ...

ответ

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

EDIT:

Пожалуйста, обратите внимание, что для того, чтобы запретить переиздание всего списка при каждом изменении объекта контейнера (например, порядок изменения фрагментов), вам необходимо создать отдельный шаблон listOfTiles, который не зависит от самого объекта контейнера.

+0

Это выглядит очень хорошо. Но так как я могу отображать много контейнеров на одной странице, я мог бы каким-то образом превратить это в функцию преобразования коллекции Containers? –

+0

Хороший вопрос! Но я предпочел бы использовать функцию 'transform' для коллекции Tiles. Обратите внимание, что главная задача здесь - выяснить, что представляет собой «индекс» определенной плитки в ее родительском списке «плитки». –

+0

Кроме того, вы можете обобщить вышеупомянутое решение (но я считаю, что правильное использование функции преобразования может быть лучшей идеей). В этом случае вам также понадобится установить поля типа '_parent' (для фрагментов копий во вспомогательной коллекции) и более тщательно обработать обратные вызовы наблюдателя. –

Смежные вопросы