我对Meteor有点新鲜,我遇到的问题是反应数据 - 特别是在我需要更改基于鼠标或键盘事件显示的数据的情况下。正常的js方式做这种事情似乎让我在流星中遇到麻烦,因为我改变的一切都会被重新渲染并不断重置。
所以,我想我会看到这是否可以使用Meteor的Deps对象,但是我无法理解它。这是我正在使用的代码:
(function(){
var tenants = [];
var selectedTenant = 0;
var tenantsDep = new Deps.Dependency;
Template.tenantsBlock.tenantsList = function()
{
tenants = [];
var property = $properties.findOne({userId: Meteor.userId(), propertyId: Session.get('property')});
var tenancies = _Utils.resolveTenancies(property, true, null, true);
for(var i = 0; i < tenancies.length; i++)
{
if(tenancies[i].tenancyId == Session.get('tenancy'))
{
tenants = tenants.concat(tenancies[i].otherTenants, tenancies[i].primaryTenant);
}
}
tenants[selectedTenant].selected = 'Selected';
tenantsDep.changed();
return tenants;
};
Template.tenantsBlock.onlyOneTenant = function()
{
tenantsDep.depend();
return tenants.length > 1 ? '' : 'OneChild';
};
Template.tenantsBlock.phoneNumber = function()
{
tenantsDep.depend();
for(var i = 0; i < tenants[selectedTenant].details.length; i++)
if(_Utils.getDynamicContactIconClass(tenants[selectedTenant].details[i].key) == 'Phone')
return tenants[selectedTenant].details[i].value;
return null;
};
Template.tenantsBlock.emailAddress = function()
{
tenantsDep.depend();
for(var i = 0; i < tenants[selectedTenant].details.length; i++)
if(_Utils.getDynamicContactIconClass(tenants[selectedTenant].details[i].key) == 'Email')
return tenants[selectedTenant].details[i].value;
return null;
};
Template.tenantsBlock.addedDate = function()
{
tenantsDep.depend();
return _Utils.timeToDateString(tenants[selectedTenant].created);
};
Template.tenantsBlock.events({
'click .Name': function(e, template)
{
tenantsDep.depend();
var _this = e.currentTarget;
var tenantName = _this.innerHTML;
$(_this).addClass('Selected');
$(_this).siblings().removeClass('Selected');
for(var i = 0; i < tenants.length; i++)
{
if(tenants[i].name == tenantName)
tenants[i].selected = "Selected";
else
tenants[i].selected = '';
}
}
})
})();
^这似乎是他们在meteor文档(http://docs.meteor.com/#deps_dependency)中为dependency.changed()和dependency.depend()所得到的,但所有这一切都给了我一个无限循环。
那么我可以修改我声明deps的方式来使数据被动反应吗?是否有更好的方法可以一起完成这些工作?
更新:
虽然我对此持怀疑态度,但我倾向于尝试以本地化方式使用Session.set / Session.get。所以,下次我必须这样做时,我会做
Session.set('tenantsBlock' {tenants: [], selectedTenant: 0});
然后只需从与Template.tenantsBlock相关的帮助程序和事件映射中访问此变量。这样,他们都可以实时访问数据,并在数据发生变化时重新运行。这是我将这个脚本转换成的内容(抱歉这些都是如此之大):
(function()
{
Template.tenantsBlock.created = Template.tenantsBlock.destroyed =function()
{
_Utils.setSession('tenantsBlock', {
tenants: [],
selectedTenant: 0
})
};
Template.tenantsBlock.tenantsList = function()
{
var localContext = Session.get('tenantsBlock');
localContext.tenants = [];
var property = $properties.findOne({userId: Meteor.userId(), propertyId: Session.get('property')});
var tenancies = _Utils.resolveTenancies(property, true, null, true);
for(var i = 0; i < tenancies.length; i++)
{
if(tenancies[i].tenancyId == Session.get('tenancy'))
{
localContext.tenants = localContext.tenants.concat(tenancies[i].otherTenants, tenancies[i].primaryTenant);
break;
}
}
localContext.tenants[localContext.selectedTenant].selected = 'Selected';
Session.set('tenantsBlock', localContext);
return localContext.tenants;
};
Template.tenantsBlock.onlyOneTenant = function()
{
var localContext = Session.get('tenantsBlock');
return localContext.tenants.length > 1 ? '' : 'OneChild';
};
Template.tenantsBlock.phoneNumber = function()
{
var localContext = Session.get('tenantsBlock');
for(var i = 0; i < localContext.tenants[localContext.selectedTenant].details.length; i++)
if(_Utils.getDynamicContactIconClass(localContext.tenants[localContext.selectedTenant].details[i].key) == 'Phone')
return localContext.tenants[localContext.selectedTenant].details[i].value;
return null;
};
Template.tenantsBlock.emailAddress = function()
{
var localContext = Session.get('tenantsBlock');
var selectedTenantDetails = localContext.tenants[localContext.selectedTenant].details;
for(var i = 0; i < selectedTenantDetails.length; i++)
if(_Utils.getDynamicContactIconClass(selectedTenantDetails[i].key) == 'Mail')
return selectedTenantDetails[i].value;
return null;
};
Template.tenantsBlock.addedDate = function()
{
var localContext = Session.get('tenantsBlock');
return _Utils.timeToDateString(localContext.tenants[localContext.selectedTenant].created);
};
Template.tenantsBlock.events({
'click .Name': function(e, template)
{
var localContext = Session.get('tenantsBlock');
var _this = e.currentTarget;
var tenantName = _this.innerHTML;
for(var i = 0; i < localContext.tenants.length; i++)
{
if(localContext.tenants[i].name == tenantName)
{
localContext.tenants[i].selected = 'Selected';
localContext.selectedTenant = i;
}
else
{
localContext.tenants[i].selected = '';
}
}
Session.set('tenantsBlock', localContext);
}
})
})();
答案 0 :(得分:15)
你必须克服老派的做法:)流星比你想象的要简单得多。 一个好的经验法则是,如果您使用jQuery来操作任何DOM元素,那么您可能做错了。此外,如果您在不使用集合API的情况下访问任何数据,那么最好有充分理由这样做。
在您的情况下,您根本不需要编写任何手动依赖项。大多数Meteor应用程序都很少需要手动依赖。
您需要做的第一件事就是将所有租户都放在Meteor.Collection
内,这样可以更轻松地使用它们。
Tenants = new Meteor.Collection("tenants");
您的tenantsBlock
模板看起来应该是这样的(模数为一些不同的html元素):
<template name="tenantsBlock">
<ol>
{{#each tenants}}
<li class="name {{selected}}">
<span>Primary Tenant: {{primaryTenant}}</span>
<span>Other Tenants: {{otherTenants}}</span>
<span>Phone Number: {{phoneNumber}}</span>
<span>Email Address: {{emailAddress}}</span>
<span>Added Date: {{addedDate}}</span>
</li>
{{/each}}
</ol>
</template>
Tenants
中的每个文档应如下所示:
{
primaryTenant: "Joe Blow",
otherTenants: "Mickey Mouse, Minnie Mouse",
phoneNumber: "555-234-5623",
emailAddress: "joe.blow@foo.com",
addedDate: "2005-10-30T10:45Z"
}
然后,您需要的所有代码仅用于选择/取消选择,您可以删除其他所有代码:
Template.tenantsBlock.tenants = function() {
return Tenants.find();
};
Template.tenantsBlock.selected = function() {
return Session.equals("selectedTenant", this._id);
};
Template.tenantsBlock.events({
'click .name': function(e) {
Session.set("selectedTenant", this._id);
}
});
我再次重申,在使用Meteor时,你永远不应该使用Javascript进行DOM操作。您只需更新数据,如果一切正确完成,模板将被动地更新。声明您希望数据显示的 ,然后更改数据并观看魔术。
答案 1 :(得分:0)
自从我在2013年发布这篇文章以来,Meteor已经真正发展了。我想 我应该发布一种现代的,优越的方法。
现在您已经能够创建ReactiveVar
,现在您可以将这些直接附加到模板。与Session类似,ReactiveVar是一个反应式数据存储。但是,ReactiveVar只保存一个值(任何类型)。
您可以通过应用程序根目录在终端中运行ReactiveVar,将ReactiveDict添加到项目的客户端:
$
的 meteor add reactive-var
强>
此javascript显示了如何在模板onCreated
,onRendered
,onDestroyed
,events
和helpers
之间传递变量。< / p>
Template.myTemplate.onCreated = function() {
// Appends a reactive variable to the template instance
this.reactiveData = new ReactiveVar('Default Value');
};
Template.myTemplate.events({
'click .someButton': (e, template) => {
// Changes the value of the reactive variable for only this template instance
template.reactiveData.set('New Value');
},
});
Template.myTemplate.helpers({
theData: () => {
// Automatically updates view when reactive variable changes
return Template.instance().reactiveData.get();
},
});
由于以下几个原因,这是优越的:
奖励积分:有关您一次在页面上有多个模板实例的情况,请参阅https://www.flixtools.com/en/osflixtools.subtitles-download/subtitles/6647724?source=source_os_landing&campaign=campaign_sub_landing,但需要管理一些反应变量并在会话期间保留这些变量。