UI helper 函数在 Meteor 中没有订阅数据
Posted
技术标签:
【中文标题】UI helper 函数在 Meteor 中没有订阅数据【英文标题】:UI helper function does not have the subscription data in Meteor 【发布时间】:2015-10-22 16:23:33 【问题描述】:我对 Meteor 还很陌生。
我有一个模板辅助函数,它需要处理我从服务器端发布的数据。当页面加载时,下面配置文件的值为undefined
。但在那之后,当我从浏览器的控制台执行相同的代码 sn-p 时,它工作得很好。据我了解,模板助手是在数据发布之前执行的。如何等到数据发布后再运行 UI 助手?
这里是相关代码。
辅助功能
Template.header.helpers(
me: function()
var user = Meteor.users.findOne(Meteor.userId());
if (user)
return Profiles.findOne(
spid: user.profile.spid
);
return null;
);
HTML 模板
<template name="header">
<header class="ui fixed inverted menu">
> thumb user=me
</header>
</template>
缩略图模板
<template name="thumb">
#with user
<div class="thumb">
<div class="text" style="background-color:color">
initials name
</div>
<div class="pic" style="background-image:url('pic')"></div>
</div>
/with
</template>
出版物
Meteor.publish('profiles', function()
return Profiles.all();
);
Meteor.publish('departments', function()
return Departments.all();
);
Meteor.publish('requestServiceIds', function()
return Requests.getServiceIds();
);
Meteor.publish('relevantServices', function()
return Services.getRelevant(this.userId, 5);
);
路由器
Router.configure(
layoutTemplate: 'main',
waitOn: function()
Deps.autorun(function()
Meteor.subscribe('profiles', Partitioner.group());
Meteor.subscribe('departments', Partitioner.group());
);
);
Router.onBeforeAction(function()
if (this.route.getName() === 'not-authorized') return this.next();
if (!Meteor.userId() || !Cookie.get('TKN'))
this.render('login');
else
this.next();
);
Router.route('/',
name: 'home',
waitOn: function()
Deps.autorun(function()
Meteor.subscribe('requestServiceIds', Partitioner.group());
Meteor.subscribe('relevantServices', Partitioner.group());
);
);
---
更新 1
我稍微更新了路由器。但这似乎没有任何影响。
Router.configure(
layoutTemplate: 'main',
waitOn: function()
// Deps.autorun(function()
// Meteor.subscribe('profiles', Partitioner.group());
// Meteor.subscribe('departments', Partitioner.group());
// );
return [
Meteor.subscribe('profiles', Partitioner.group()),
Meteor.subscribe('departments', Partitioner.group())
];
);
Router.route('/',
name: 'home',
waitOn: function()
// Deps.autorun(function()
// Meteor.subscribe('requestServiceIds', Partitioner.group());
// Meteor.subscribe('relevantServices', Partitioner.group());
// );
return [
Meteor.subscribe('requestServiceIds', Partitioner.group()),
Meteor.subscribe('relevantServices', Partitioner.group())
];
);
【问题讨论】:
为什么在waitOn
函数中使用Deps.autorun
?你能试试waitOn: function () return [Meteor.subscribe('profiles', Partitioner.group()), Meteor.subscribe('departments', Partitioner.group())];
和waitOn: function () return [Meteor.subscribe('requestServiceIds', Partitioner.group()), Meteor.subscribe('relevantServices', Partitioner.group())];
吗?
@MatthiasEckhart:我使用的是Deps
,因为我使用的是Partitioner
包,这是atmospherejs.com/mizzao/partitioner 推荐的
@MatthiasEckhart:我只是按照建议尝试过,似乎没有任何区别
好吧,waitOn
应该在订阅准备好之前阻止模板呈现。也许您可以使用guard expression 来解决您的问题。
【参考方案1】:
创建一个像这样的哑加载模板(使用字体真棒):
<template name="loading">
<div class="loading">
<i class="fa fa-circle-o-notch fa-4x fa-spin"></i>
</div>
</template>
并尝试将您的 Router.configure()
部分替换为以下内容:
Router.configure(
layoutTemplate: 'main',
action: function()
if(this.isReady()) this.render(); else this.render("loading");
,
isReady: function()
var subs = [
Meteor.subscribe('profiles', Partitioner.group());
Meteor.subscribe('departments', Partitioner.group());
];
var ready = true;
_.each(subs, function(sub)
if(!sub.ready())
ready = false;
);
return ready;
,
data: function()
return
params: this.params || ,
profiles: Profiles.find(),
departments: Departments.find()
;
);
我想这可以使用waitOn
来实现,但由于你的方法行不通,我给你一个我每天都用的有效食谱。代码灵感来自meteor Kitchen 生成的代码。
回答你的cmets:
关于Action
没有被触发,可能是因为我们试图放入Router.configure
里面。我不这样做,这里有一些关于我如何实现它的细节。
首先,我在 router.js 文件中为每个路由设置了一个控制器(我也有 Router.configure()
函数。看起来像这样:
Router.map(function ()
this.route("login", path: "/login", controller: "LoginController");
// other routes
接下来,我创建一个控制器,将其存储在与客户端视图模板相同的文件夹中。看起来是这样的:
this.LoginController = RouteController.extend(
template: "Login",
yieldTemplates:
/*YIELD_TEMPLATES*/
,
onBeforeAction: function()
/*BEFORE_FUNCTION*/
this.next();
,
action: function()
if(this.isReady()) this.render(); else this.render("loading");
/*ACTION_FUNCTION*/
,
isReady: function()
var subs = [
];
var ready = true;
_.each(subs, function(sub)
if(!sub.ready())
ready = false;
);
return ready;
,
data: function()
return
params: this.params ||
;
/*DATA_FUNCTION*/
,
onAfterAction: function()
);
所以当我使用控制器扩展路由时,这个action
函数正在工作。也许它会解决你的问题。
为了完整起见,这是我的Router.configure()
的样子:
Router.configure(
templateNameConverter: "upperCamelCase",
routeControllerNameConverter: "upperCamelCase",
layoutTemplate: "layout",
notFoundTemplate: "notFound",
loadingTemplate: "loading",
//I removed the rest because it is useless.
);
【讨论】:
试过了。不工作。有了这个部门也停止了工作。 好吧,action
函数没有被调用。我在动作函数中添加了console.log('test')
,但没有得到任何输出。以上是关于UI helper 函数在 Meteor 中没有订阅数据的主要内容,如果未能解决你的问题,请参考以下文章
Meteor Account UI Bootstrap 登录回调