如何摆脱流星模板闪烁

时间:2015-02-03 18:02:05

标签: javascript meteor iron-router

我有一个具有多个条件的Meteor模板,并且在最初加载时我会看到一些条件视图的闪烁。

我正在使用铁路由器,我知道订阅,wait()和ready()选项,但其中一个问题是主条件isInstalled取决于meteor.call回调到设置isInstalled变量,因此wait不依赖于订阅。那么我该如何解释这个用例?

<template name="adminLayout">
    {{#if isInstalled}}
        {{#if currentUser}}
            {{> adminHeader}}
            <br /><br />
            <div class="row">  
              <div class="medium-3 columns">
              {{> adminNav}}
              </div>
              <div class="medium-9 columns">
                {{> yield}}
              </div>
            </div>
            <div class="row">
              <div class="medium-12 columns">
              {{> adminFooter}}
              </div>
            </div>
        {{else}}
            {{> login}}
        {{/if}}
    {{else}}
        {{> install}} 
    {{/if}}
</template>

这是我的模板助手,说明了我如何为isInstalled

提供价值
Meteor.call('isInstalled', function (err, result) {
  if (err) {
    console.log(err);
  }
  Session.set('isInstalled', result);
});

Template.adminLayout.helpers({
  isInstalled: function () {
    return Session.get('isInstalled');
  }
});

最后一条路线:

Router.route('/admin', function () {
  this.layout('adminLayout');
  this.render('dashboard');
});

2 个答案:

答案 0 :(得分:0)

onBeforeAction钩子怎么样?当然你必须有/ login和/ install的其他路由,但我认为这将是更好的方法,因为用户应该能够浏览网址,如:

Router.onBeforeAction(function() {
    if (!Meteor.userId()) {
        Router.go('/login');
        this.next();
    } else {
        if (/*check somehow if installed*/) {
            this.next();
        }else{
          Router.go('/install');
          this.next();
        }
    }
});

答案 1 :(得分:0)

事实证明闪烁问题实际上是Meteor问题,而不是Iron Router问题,尽管铁路由器可以提供一种解决方法来使用其wait()和ready()方法来解决问题。

在我的特定情况下,我并不需要等待订阅,而是要求Meteor.call结果。为了实现这一点,我创建了一个匿名函数,它返回一个对象句柄,其中包含一个铁路由器可以理解的就绪方法,我稍后可以在路由逻辑中实现。

Sindis指导我朝着正确的方向前进,虽然这是一个不完整的解决方案。以下是我完成它的方法:

Router.onBeforeAction(function (params) {
    var self = this;
    if (params.url.match(/admin/)) {
        this.wait(function(){
            Meteor.call('isInstalled', function (err, result) {
                Session.set('installationCheck', true);
                Session.set('isInstalled', result);
            });
            return {
                ready: function () {
                    return Session.get('installationCheck');
                    self.next();
                }
            }   
        });
        if (this.ready()) {
            if (Session.get('isInstalled')) {
                this.next();
            } else if(Session.get('isInstalled') === false) {
                console.log('go to install!');
                this.render('install');
            }
        }
    } else {
        this.next();
    }
});

这是一个更通用的模式,允许您根据异步条件设置路由

Router.onBeforeAction(function (params) {
    var self = this;
    this.wait(function(){
        Meteor.call('someMethod', function (err, result) {
            Session.set('someMethodCalled', true);
            // do whatever with result...
            Session.set('someCondition', true); 
        });
        return {
            ready: function () {
                return Session.get('someMethodCalled');
                self.next();
            }
        }   
    });
    if (this.ready()) {
        if (Session.get('someCondition')) {
            this.next();
        } else if(Session.get('someCondition') === false) { // important to be explicit ===
            this.render('someSpecificRoute');
        }
    }
});