2013-07-30 6 views
0

Почему шаблон получает отображаемое количество раз, которое коррелирует с каждым в моем шаблоне.Шаблон #each & rendering

<template name="carousel"> 
<div class="pikachoose"> 
<ul class="carousel" > 
{{#each article}} 
    <li><a href="#"><img src="{{image}}" width="500" height="250" alt="picture"/></a><span>{{caption}}</span></li> 
{{/each}} 
    </ul> 
    </div> 

</template> 

Template.carousel.article = function() { 
return News.find({},{limit: 3}); 

} 

Template.carousel.rendered = function() { 
//$(".pika-stage").remove(); 
alert($(".carousel").html()); 
//$(".carousel").PikaChoose({animationFinished: updateNewsPreview}); 
} 

В этом случае он будет предупреждать 3 раза.

ответ

0

Возможно, проблема связана с использованием обратного вызова .rendered. Каждый раз, когда цикл запускается, DOM обновляется, поэтому обратный вызов снова запускается.

Когда у меня была эта проблема в прошлом, я счел полезным использовать обработчики событий Meteor, когда это возможно, для устранения проблем с загрузкой, таких как этот. В этом случае, возможно, вы можете попробовать тайм-аут, чтобы вызовы .remove() и .PikaChoose() запускались только после того, как DOM был тихим на определенный интервал. Надеюсь, это сработает для вас.

+1

' .rendered' не является причиной проблемы, а является индикатором. Проблема заключается в побочном эффекте реактивности. Кроме того, использование тайм-аутов для ожидания получения данных - это ужасная ** идея. –

+0

Вы делаете хороший момент, сэр. –

1

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

 


 

Если вы должны быть уверены, что ваш код работает только один раз, есть несколько возможностей, в зависимости от того, что вам нужно.

Самый простой способ - использовать только created вместо rendered.

Если вы изменяете элементы DOM, вы также можете пометить элементы, изменить так, что вы не будете их обрабатывать дважды:

Template.carousel.rendered = function() { 
    _.each(this.findAll('.class'), function(element){ 
     if($(element).data('modified')) return; 
     $(element).data('modified', true); 
     ... 
    }); 
}; 

Вы можете отключить реактивность для курсора, хотя это печальное решение:

Articles.find(..., {reactive: false}); 

наиболее инвазивная, но и наиболее универсальным является наблюдение, когда данные полностью загружены:

Deps.autorun(function() { 
    Meteor.subscribe('articles', { 
     ready: function() { 
      ... 
     }, 
    }); 
});