使用Iron-Router在模板中的上下文

时间:2014-01-07 16:20:38

标签: templates meteor

我无法理解完全在Meteor与铁路由器调用的模板中作为我的上下文可用的内容 - 以及这些内容如何继承。

以下是我能想到的“我可以在双花括号内引用的东西”的所有潜在来源:

  • 内置助手
  • Handlebars.registerHelper(...)
  • Template.myTemplate.myVar/myHelper = ...
  • Template.myTemplate.helpers({ ... })
  • 路由内的
  • data: { ... }(Router.map)
  • #each有什么关系?
  • #with有什么关系?

我忘了什么吗?有没有全局变量?

我想我对于首先为模板提供上下文的标准方法有点困惑。还有关于#each#with等控制结构内部发生的事情。

澄清会很棒!

1 个答案:

答案 0 :(得分:4)

IronRouter使用RouteController.data的结果呈现模板作为当前数据上下文。

<template name="viewPost">
   <div>
        <h1>{{title}}</h1>
        <p>{{content}}</p>
    </div>
</template>

var PostsController=RouteController.extend({
    template:"viewPost",
    waitOn:function(){
        return Meteor.subscribe("postsById",this.params._id);
    },
    data:function(){
        return Posts.findOne(this.params._id);
    }
});

this.route("viewPost",{
    path:"/posts/:_id",
    controller:PostsController
});

在此示例中,IronRouter将使用this.params._id作为数据上下文的帖子呈现“viewPost”模板。

首先为模板提供上下文的标准方法是什么?

有两种方式:

{{#with myContext}}
    {{> myTemplate}}
{{/with}}

{{> myTemplate myContext}}

如您所见,#with控制结构设置当前数据上下文。 #each结构遍历Cursor(或Array)并将当前数据上下文设置为当前获取的文档(或当前单元格)。

<template name="postsList">
    {{#each posts}}
        <h1>{{title}}</h1>
    {{/each}}
</template>

Template.postsList.helpers({
    posts:function(){
        // cursor
        return Posts.find();
        // array
        return [{title:"Title 1"},{title:"Title 2"},{title:"Title 3"}];
    }
});

更新:您是否可以添加有关继承的说明?例如,如果我有嵌套的#each块,那么执行变量cascade吗?

我想出了这个例子:

<template name="parent">
    <ul>
        {{#each parentContexts}}
            {{> child}}
        {{/each}}
    </ul>
</template>

<template name="child">
    <li>
        <ul>
            {{#each childContexts}}
                {{> content}}
                <p>../this.parentProperty = {{../this.parentProperty}}</p>
            {{/each}}
        </ul>
    </li>
</template>

<template name="content">
    <li>
        <p>this.childProperty = {{this.childProperty}}</p>
        <p>this.parentProperty = {{this.parentProperty}}</p>
    </li>
</template>

Template.parent.helpers({
    parentContexts:function(){
        return [{
            parentProperty:"parent 1"
        },{
            parentProperty:"parent 2"
        }];
    }
});

Template.child.helpers({
    childContexts:function(){
        return [{
            childProperty:"child 1"
        },{
            childProperty:"child 2"
        }];
    }
});

如果您运行此示例,您将注意到您无法访问“content”中的parentProperty,因为默认的#each帮助程序会使用提供的新上下文覆盖父数据上下文。

您可以使用以下语法访问嵌套#each块中的parentProperty:.. / this.parentProperty,这让人联想到UNIX父目录访问语法。

但是,您无法在“内容”模板中使用此语法,因为它与嵌套的每个结构无关:它只能在实际嵌套的模板中使用../../ parent语法发生的情况。

如果我们想要访问内容模板中的parentPropery,我们必须使用父上下文扩充当前数据上下文。

为此,我们可以注册一个新的#eachWithParent助手:

Handlebars.registerHelper("eachWithParent",function(context,options){
    var parentContext=this;
    var contents="";
    _.each(context,function(item){
        var augmentedContext=_.extend(item,parentContext);
        contents+=options.fn(augmentedContext);
    });
    return contents;
});

现在,如果用这个新帮助器替换嵌套的#each,您将可以访问“content”中的parentProperty。