【发布时间】:2013-09-18 18:17:34
【问题描述】:
我对 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 = '';
}
}
})
})();
^这似乎是他们在流星文档 (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);
}
})
})();
【问题讨论】:
-
Session 变量中只能设置字符串。我仍然不明白你想用这段代码做什么。为什么不能把
localContext.tenants放在一个集合中,把selectedTenant放在一个会话变量中? -
我不知道,伙计。 session 变量似乎可以很好地存储一个对象。需要注意的是,我无法使用 Session.get('tenantsBlock.selectedTenant') 访问它,但它仍会将“tenantsBlock”的值存储为对象并将其原样返回。也就是说,除非您知道这样做存在跨浏览器问题。
-
我必须承认我不太习惯将控制数据放入数据库。存储和检索数据似乎是一种笨拙的方式,另外,如果我为我的应用程序中的每个模板控件 + 所有正常的数据库集合都这样做,我将拥有至少 30 个数据库集合。作为对全局可访问控制数据的妥协,Session 变量似乎更有效。
-
您对 Session 的看法可能是正确的;但是,您可以在客户端和服务器端(不与 Mongo 同步)创建匿名集合。这些将允许您访问无法通过 Session 访问的嵌套字段。我仍然不明白您所说的“控制数据”是什么意思,因为我认为您没有非常清楚地解释您的应用需要做什么。
-
匿名集合:
new Meteor.Collection(null)仅用于客户端/服务器集合,new Meteor.Collection("name", {connection: null})用于仅在内存中的客户端/服务器同步集合。根据您的解释,我将创建一个Properties集合和一个在属性中引用_ids 的Tenants集合。然后将任何上下文放入Session或匿名集合中。这将摆脱您在这里筛选原始 Javascript 对象的所有麻烦。看看我在那里链接的应用程序,它有一个这样做的例子。
标签: meteor reactive-programming