How to get rid of Meteor template flickers

柔情痞子 提交于 2020-01-03 04:21:14

问题


I have a Meteor template with multiple conditions, and I get a flicker of some of the conditional views when it loads initially.

I'm using iron router and I'm aware of the subscriptions, wait() and ready() options, however one of the problems is that the main conditional isInstalled depends on a meteor.call callback to set the isInstalled variable, so the wait doesn't depend on a subscription. So how do I account for this use case?

<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>

Here's my Template helper, illustrating how I'm providing the value for 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');
  }
});

And lastly the route:

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

回答1:


How about onBeforeAction hook? Of course you would have to have other routes for /login and /install but I think that would be better approach because user should be able to navigate through url, something like:

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



回答2:


As it turns out the flickering issue is really a Meteor issue, not an Iron Router one, though iron router can provide a workaround to solve the problem using its wait() and ready() methods.

In my particular case I didn't require a wait on a subscription but on a Meteor.call result. In order to achieve this I created an anonymous function that return an object handle with a ready method that Iron Router could understand and I could later implement in the route logic.

Sindis guided me in the right direction though it was an incomplete solution. Below is how I accomplished it:

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

And here is a more general pattern which allows you to set routes based on asynchronous conditions

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


来源:https://stackoverflow.com/questions/28305666/how-to-get-rid-of-meteor-template-flickers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!