【问题标题】:How to get the parent template instance (of the current template)如何获取(当前模板的)父模板实例
【发布时间】:2015-03-13 00:26:24
【问题描述】:

有没有一种干净的方法来获取当前模板的父模板? Meteor 的 API 中没有任何正式记录。 我说的是Blaze.TemplateInstance,而不是上下文(即不是Template.parentData)。

【问题讨论】:

    标签: meteor meteor-blaze


    【解决方案1】:

    你可以使用像Aldeed's template-extension这样的包

    这里有以下方法:

    templateInstance.parent(numLevels, includeBlockHelpers)
    

    【讨论】:

      【解决方案2】:

      如果您不想扩展 Blaze.TemplateInstance,您可以像这样访问父实例:

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

      仅在 Meteor 1.4.x 中测试

      【讨论】:

        【解决方案3】:

        最后,我用 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() 获取直接父级

        【讨论】:

        • 我不得不将“var view = Blaze.currentView”更改为“var view = this.view;”否则 "someTemplate.parentTemplate(2) != someTemplate.parentTemplate().parentTemplate()"
        • 好点,@GraemePyle。我已经将近一年没有使用 Blaze(并且不记得当时 TemplateInstance 是否提供 view),但我相信你的话并编辑了答案。干杯
        • 我可以验证此代码是否可以访问父模板实例。它是实际实例,包括最初加载时附加到父实例的任何参数。想知道为什么 Blaze 没有为此提供官方 API 吗?他们只有它,因此您可以访问 parentData 但不能访问实例。希望这不会在 Blaze 的未来更新中中断。
        • 填补 Blaze API 漏洞的好方法,它可以按原样工作。我对依靠模板名称字符串比较来工作感到不安,所以我建议将view.name.substring(0, 9) === "Template." 更改为view.hasOwnProperty('template')
        • 听起来不错,@cstricklan,请随时编辑答案。我也喜欢多查view.template,但我自己不会改答案,因为我一年多没用过blaze
        【解决方案4】:

        到目前为止,我一直在做的是,如果我需要访问子模板函数中的父实例,我会尝试重构此函数以在 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();
          }
        });
        

        【讨论】:

          【解决方案5】:

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

          目前,我不知道,但这应该会在未来某个时候发生,作为计划中的“用于设计可重用组件的更好 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;
              }
            }
          });
          

          【讨论】:

          • 感谢@saimeunt 的详尽回答!不完全是我想要的,但仍然有用。我已经构建了一个类似于流星parentData 的函数,但我赞成你的答案,因为closest 也是一个有用的模式
          猜你喜欢
          • 2012-06-24
          • 2019-09-04
          • 2012-05-05
          • 2011-02-22
          • 1970-01-01
          • 2015-05-05
          相关资源
          最近更新 更多