如何摆脱 Meteor 模板闪烁
How to get rid of Meteor template flickers
我有一个具有多个条件的 Meteor 模板,在最初加载时我发现一些条件视图闪烁。
我正在使用 iron router,我知道订阅、wait() 和 ready() 选项,但是其中一个问题是主要条件 isInstalled
取决于 meteor.call 回调来设置 isInstalled 变量,因此等待不依赖于订阅。那么我该如何解释这个用例呢?
<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');
});
onBeforeAction 钩子怎么样?当然,您必须为 /login 和 /install 使用其他路由,但我认为这是更好的方法,因为用户应该能够通过 url 导航,例如:
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();
}
}
});
事实证明,闪烁问题实际上是一个 Meteor 问题,而不是 Iron Router 问题,尽管 Iron Router 可以使用其 wait() 和 ready() 方法提供一种解决方法来解决该问题。
在我的特殊情况下,我不需要等待订阅,而是等待 Meteor.call 结果。为了实现这一点,我创建了一个匿名函数,该函数 return 一个具有 Iron Router 可以理解的现成方法的对象句柄,我稍后可以在路由逻辑中实现。
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');
}
}
});
我有一个具有多个条件的 Meteor 模板,在最初加载时我发现一些条件视图闪烁。
我正在使用 iron router,我知道订阅、wait() 和 ready() 选项,但是其中一个问题是主要条件 isInstalled
取决于 meteor.call 回调来设置 isInstalled 变量,因此等待不依赖于订阅。那么我该如何解释这个用例呢?
<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');
});
onBeforeAction 钩子怎么样?当然,您必须为 /login 和 /install 使用其他路由,但我认为这是更好的方法,因为用户应该能够通过 url 导航,例如:
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();
}
}
});
事实证明,闪烁问题实际上是一个 Meteor 问题,而不是 Iron Router 问题,尽管 Iron Router 可以使用其 wait() 和 ready() 方法提供一种解决方法来解决该问题。
在我的特殊情况下,我不需要等待订阅,而是等待 Meteor.call 结果。为了实现这一点,我创建了一个匿名函数,该函数 return 一个具有 Iron Router 可以理解的现成方法的对象句柄,我稍后可以在路由逻辑中实现。
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');
}
}
});