【发布时间】:2015-03-13 00:26:24
【问题描述】:
有没有一种干净的方法来获取当前模板的父模板? Meteor 的 API 中没有任何正式记录。
我说的是Blaze.TemplateInstance,而不是上下文(即不是Template.parentData)。
【问题讨论】:
标签: meteor meteor-blaze
有没有一种干净的方法来获取当前模板的父模板? Meteor 的 API 中没有任何正式记录。
我说的是Blaze.TemplateInstance,而不是上下文(即不是Template.parentData)。
【问题讨论】:
标签: meteor meteor-blaze
你可以使用像Aldeed's template-extension这样的包
这里有以下方法:
templateInstance.parent(numLevels, includeBlockHelpers)
【讨论】:
如果您不想扩展 Blaze.TemplateInstance,您可以像这样访问父实例:
Template.exampleTemplate.onRendered(function () {
const instance = this;
const parentInstance = instance.view.parentView.templateInstance();
});
仅在 Meteor 1.4.x 中测试
【讨论】:
最后,我用 Meteor 的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() 获取直接父级
【讨论】:
TemplateInstance 是否提供 view),但我相信你的话并编辑了答案。干杯
view.name.substring(0, 9) === "Template." 更改为view.hasOwnProperty('template')
view.template,但我自己不会改答案,因为我一年多没用过blaze
到目前为止,我一直在做的是,如果我需要访问子模板函数中的父实例,我会尝试重构此函数以在 parent 模板上声明它,并且然后将它作为参数传递给孩子,然后孩子可以执行它。
例如,假设我想从子模板中增加父模板上的模板变量。我可以这样写:
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();
}
});
【讨论】:
有没有一种干净的方法来获取当前的父模板 模板?
目前,我不知道,但这应该会在未来某个时候发生,作为计划中的“用于设计可重用组件的更好 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 相同的方式工作,以从子视图到最顶层模板(主体)遍历父视图节点,搜索适当命名的模板。
在您的客户端代码中的某处注册 Blaze 扩展后,您可以执行以下操作:
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;
}
}
});
【讨论】:
parentData 的函数,但我赞成你的答案,因为closest 也是一个有用的模式