2015-01-14 54 views

回答

27

最后,我使用流星的parentData类似地扩展了模板实例,如下所示:

/** 
* Get the parent template instance 
* @param {Number} [levels] How many levels to go up. Default is 1 
* @returns {Blaze.TemplateInstance} 
*/ 

Blaze.TemplateInstance.prototype.parentTemplate = function (levels) { 
    var view = this.view; 
    if (typeof levels === "undefined") { 
     levels = 1; 
    } 
    while (view) { 
     if (view.name.substring(0, 9) === "Template." && !(levels--)) { 
      return view.templateInstance(); 
     } 
     view = view.parentView; 
    } 
}; 

用法示例:someTemplate.parentTemplate()获得直接父

+1

我不得不改变 “VAR视图= Blaze.currentView” 到 “var view = this.view;” 否则 “someTemplate.parentTemplate(2)!= someTemplate.parentTemplate()。parentTemplate()” –

+0

好点,@GraemePyle。我近一年没有使用Blaze(并且不记得当时'TemplateInstance'中是否有'view'可用),但是我接受了你的话并编辑了答案。干杯 –

+0

我可以验证此代码是否可以访问父模板实例。它是实际的实例,包括最初加载时附加到父实例的任何参数。不知道为什么Blaze没有这个官方API?他们只有它,所以你可以访问parentData而不是实例。希望这在未来的Blaze更新中不会中断。 – nearpoint

11

有没有一种干净的方式来获取当前 模板的父模板?

目前,没有,我知道的,但这应该在未来的计划“设计的可重用组件更好的API”的一部分,有时发生(这是在Meteor post 1.0 roadmap讨论)。

就目前而言,这里是我用在我的项目解决方法:

// extend Blaze.View prototype to mimick jQuery's closest for views 
_.extend(Blaze.View.prototype,{ 
    closest:function(viewName){ 
     var view=this; 
     while(view){ 
      if(view.name=="Template."+viewName){ 
       return view; 
      } 
      view=view.parentView; 
     } 
     return null; 
    } 
}); 

// extend Blaze.TemplateInstance to expose added Blaze.View functionalities 
_.extend(Blaze.TemplateInstance.prototype,{ 
    closestInstance:function(viewName){ 
     var view=this.view.closest(viewName); 
     return view?view.templateInstance():null; 
    } 
}); 

注意,这是仅支持命名父模板,应该以同样的方式工作,因为jQuery的closest遍历父查看从一个孩子到最顶层模板(正文)的节点,搜索适当命名的模板。

一旦这个扩展大火已在客户端代码的地方注册,你可以做这样的东西:

HTML

<template name="parent"> 
    <div style="background-color:{{backgroundColor}};"> 
    {{> child}} 
    </div> 
</template> 

<template name="child"> 
    <button type="button">Click me to change parent color !</button> 
</template> 

JS

Template.parent.created=function(){ 
    this.backgroundColor=new ReactiveVar("green"); 
}; 

Template.parent.helpers({ 
    backgroundColor:function(){ 
    return Template.instance().backgroundColor.get(); 
    } 
}); 

Template.child.events({ 
    "click button":function(event,template){ 
    var parent=template.closestInstance("parent"); 
    var backgroundColor=parent.backgroundColor.get(); 
    switch(backgroundColor){ 
     case "green": 
     parent.backgroundColor.set("red"); 
     break; 
     case "red": 
     parent.backgroundColor.set("green"); 
     break; 
    } 
    } 
}); 
+0

感谢您的精心解答@saimeunt!不完全是我想要的,但很有用。我已经建立了就像流星的'parentData'的功能,但我upvoting你的答案,因为'closest'也是一个有用的模式 –

9

我到目前为止一直在做的是,如果我需要访问一个子模板的功能父实例,我尝试,而不是重构这个函数声明它在父级模板上,然后将它作为参数传递给子,然后可以执行它。

作为一个例子,假设我想在子模板中的父模板上增加一个模板变量。我可以写这样的事:

Template.parentTemplate.onCreated(function() { 
    var parentInstance = this; 
    parentInstance.count = new ReactiveVar(1); 
}); 

Template.parentTemplate.helpers({ 
    incrementHandler: function() { 
    var parentInstance = Template.instance(); 
    var count = parentInstance.count.get(); 

    return function() { 
     var newCount = count + 1; 
     parentInstance.count.set(newCount); 
    }; 
    } 
}); 

然后包括我的孩子的模板:

{{> childTemplate handler=loadMoreHandler}} 

并成立了我的事件:

Template.childTemplate.events({ 
    'click .increment-button': function (event, childInstance) { 
    event.preventDefault(); 
    childInstance.data.handler(); 
    } 
}); 
2

如果你不希望延长Blaze.TemplateInstance你可以像这样访问父实例:

Template.exampleTemplate.onRendered(function() { 
    const instance = this; 
    const parentInstance = instance.view.parentView.templateInstance(); 
}); 

只在流星1.4.x测试过

+1

经过了1.5测试,并且正常工作:) – Daniel