会话更改中的订阅被动响应会导致#each重绘每个实体

时间:2014-12-02 23:41:59

标签: session meteor reactive-programming

所以这里有一个问题:我使用this neat solution存储用户的坐标。这是我的实施:

updateLoc = function () {
    var position = Geolocation.latLng() || {lat:0,lng:0};
    Session.set('lat', position.lat);
    Session.set('lon', position.lng);
};

Meteor.startup(function() {
    updateLoc(); // set at 0, 0 to begin with
    Meteor.setTimeout(updateLoc, 1000); // get first coordinates 1 second in
    Meteor.setInterval(updateLoc, 5000); // then, every 5 seconds
});

根据这两个会话变量,我有entitiesList路由等待要订阅的实体:

this.route('entitiesList', {
    path: '/',
    waitOn: function() {
        if (Meteor.userId())
            return Meteor.subscribe('entities', {lat: Session.get('lat'),lon: Session.get('lon')});
    },
    data: function() {
        return {entities: Entities.find()};
    }
});

这是出版物:

Meteor.publish('entities', function (position) {
    if (position.lon !== null && position.lat !== null) {
        return Entities.find({location: {
            $near: {$geometry:{type: "Point", coordinates: [position.lon, position.lat]},$maxDistance:500}}
        }});
    }
    this.ready();
});

最后,entitiesList模板:

<template name="entitiesList">
  <div class="entities">
    <h1>Entities list</h1>
    {{#each entities}}
      {{> entityItem}}
    {{else}}
        <p>No entity found. Looking up...</p>
        {{>spinner}}
    {{/each}}
  </div>
</template>

现在!此解决方案有效。实体列出正确,根据用户的位置每5秒更新一次。

唯一的问题在于渲染:当反应性是由于更新了Session变量时,整个实体集将被删除并重新绘制。但是当实体集合中发生更改(例如,实体被删除/创建)时,只会在模板中相应地重新呈现此更改。

这会产生一个每5秒钟非常烦人的列表。我想删除#each块,并在模板的this.autorun()函数中使用rendered自行编写,并使用jQuery以更优化的方式重绘列表,但它将是一个讨厌的黑客,在模板文件之外的HTML代码块......当然还有另一种方式!

2 个答案:

答案 0 :(得分:1)

每次更改会话变量时,您的订阅都会加载,Iron Router会设置加载模板,这就是闪烁的原因。

您可以这样做,而不是使用铁路由器:

Template.entitiesList.created=function()
{
    var self=this
    this.isLoading=new ReactiveVar(false)
    this.isFirstLoading=new ReactiveVar(true)
    this.autorun(function(){

        self.isLoading.set(true)
        Meteor.subscribe('entities', {lat: Session.get('lat'),lon: Session.get('lon')},function(err){
            self.isLoading.set(false)
            self.isFirstLoading.set(false)
        });
    })
}
Template.entitiesList.helpers({
    entities:function(){return Entities.find()}
    isLoading:function(){Template.instance().isLoading.get()
    isFirstLoading:function(){Template.instance().isFirstLoading.get()
})


<template name="entitiesList">
  <div class="entities">
    <h1>Entities list</h1>
    {{#if isFirstLoading}}
       <p>Looking up...<p/>
       {{>spinner}}
    {{else}}
        {{#each entities}}
            {{> entityItem}}
        {{else}}
            <p>No entity found</p>
        {{/each}}
        {{#if isLoading}}
            {{>spinner}}
        {{/if}}
    {{/if}}
  </div>
</template>

答案 1 :(得分:0)

摆弄铁路由器,我发现实际上有一个选项可以在每次触发的新订阅中呈现加载模板:the subscriptions option。只需将waitOn替换为subscriptions,我就会得到所需的结果。