Meteor - 如何在帮助程序和模板事件之间传递数据?

Dom*_*rez 6 reactive-programming meteor

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


})();
Run Code Online (Sandbox Code Playgroud)

^这似乎是他们在流明文档(http://docs.meteor.com/#deps_dependency)中为dependency.changed()和dependency.depend()所得到的,但所有这一切都给了我无限的环.

那么我可以修改我声明deps的方式来使这个数据被动反应吗?有没有更好的方法一起完成这一切?

更新:

虽然我对此持怀疑态度,但我倾向于尝试以本地化的方式使用Session.set/Session.get.所以,下次我必须这样做,我会做的

Session.set('tenantsBlock' {tenants: [], selectedTenant: 0});
Run Code Online (Sandbox Code Playgroud)

然后只需从与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);
    }
})

})();
Run Code Online (Sandbox Code Playgroud)

And*_*Mao 15

你必须克服老派的做法:)流星比你想象的要简单得多.一个好的经验法则是,如果你使用jQuery来操作任何DOM元素,你可能做错了.此外,如果您在不使用集合API的情况下访问任何数据,那么您最好有充分的理由这样做.

在您的情况下,您根本不需要编写任何手动依赖项.大多数Meteor应用程序很少需要手动依赖.

您需要做的第一件事就是将所有租户都放在一起Meteor.Collection,这将使他们更容易使用.

Tenants = new Meteor.Collection("tenants");
Run Code Online (Sandbox Code Playgroud)

您的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>
Run Code Online (Sandbox Code Playgroud)

每个文档Tenants应如下所示:

{
    primaryTenant: "Joe Blow",
    otherTenants: "Mickey Mouse, Minnie Mouse",
    phoneNumber: "555-234-5623",
    emailAddress: "joe.blow@foo.com",
    addedDate: "2005-10-30T10:45Z"
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要的所有代码仅用于选择/取消选择,您可以删除其他所有代码:

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);
    }
});
Run Code Online (Sandbox Code Playgroud)

我再次重申,在使用Meteor时,你永远不应该使用Javascript进行DOM操作.您只需更新数据,如果一切正确完成,您的模板将被动地更新.声明如何你想你的数据看,然后更改数据,并观看魔术.