2015-01-14 51 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