【问题标题】:Sharing functions between templates in Meteor在 Meteor 中的模板之间共享功能
【发布时间】:2017-01-04 05:17:35
【问题描述】:

如果我有两个车把模板想要检查同一个函数的返回值怎么办?有正确的方法吗?显然我可以这样做:

var say_foo = function() {
  alert('foo');
};

Template.foo.say_foo = say_foo;
Template.bar.say_foo = say_foo;

但是有什么方法可以直接通过 Template 对象执行此操作吗?由于这是 JavaScript,我可以将函数分配给任何对象的任何属性,但我尝试这样做:

Template.say_foo = function() { alert('foo'); };

当然模板没有找到这个功能。

只是对最佳实践等感到好奇。谢谢!

【问题讨论】:

    标签: meteor


    【解决方案1】:

    我认为更好的版本会是(如果您使用默认设置的 Handlebars):

    Template.registerHelper('my_helper', function() {
         // code
    });
    

    您可以使用 {{my_helper}} 从任何模板调用它!

    希望对你有帮助:)

    【讨论】:

    • 根据流星文档,正确的方法是使用 UI.registerHelper。请在下面查看我的答案。
    • @srinivas:“正确的方式”在 Meteor 的整个历史中都发生了变化,它是 Handlebars,然后是 UI,现在是 Template。应该编辑过时的原始答案,而不是发布创建难以阅读的列表的新答案。我已经相应地更新了这个,因为它是第一个也是最受欢迎的
    • @BogdanD 对于模板之间的功能共享,我觉得还是要在UI中注册为一个功能,否则模板之间的功能将无法共享。是的,我本可以将答案放在评论中,但我认为这很难找到。
    • @srinivas,我的意思是编辑答案,而不是评论(我对这个答案的编辑正在等待批准,这就是为什么不在答案中)。关于 UI - 现在已弃用,模板取而代之。
    【解决方案2】:

    根据 Meteor 文档,正确的方法是使用 UI 命名空间,它将绑定到下面使用的任何模板引擎,而不是直接使用 Handlebars 或空格键。这是文档中的链接。 http://docs.meteor.com/#ui_registerhelper

    因此,要从 client.js 中使用的任何模板访问通用函数:

    UI.registerHelper('stub', function() {
         // code
    });
    

    更新:

    显然是docs have changed back to using

    Template.registerHelper('stub', function() {
         // code
    });
    

    然后在html文件中使用{{stub}}来访问变量。

    【讨论】:

    • 谢谢,当我发布问题时,我认为这不存在。为了使这个问题保持相关性,将其更改为已接受的答案似乎是合适的。
    • 文档现已切换回使用Template.registerHelper
    • 所以是全有还是全无?从语义上讲,如果我创建一个子模板,我应该继承父模板的所有功能
    【解决方案3】:

    这是我想出的解决问题的方法。这是使用 CoffeeScript 完成的。如果您不使用 CoffeeScript,可以将其转换为 JavaScript here

    首先,定义extendTemplate函数:

    extendTemplate = (template, mixin) ->
      helpers = ({name, method} for name, method of mixin when name isnt "events")
      template[obj.name] = obj.method for obj in helpers
    
      if mixin.events?
        template.events?.call(template, mixin.events)
    
      template
    

    然后,声明一个您希望在多个模板之间共享的具有帮助器和事件的对象(我的称为 loginMixin):

    loginMixin =
      merge_with_email: ->
        return Session.get 'account_merge__merge_with_email'
    
      events:
        'click button#merge_login': (event, template) ->
    
          email = $(template.find('#email')).val()
          password = $(template.find('#password')).val()
    
          Meteor.loginWithPassword email, password, (error)->
            if error
              console.error "Failed to login."
    
          return false
    

    然后,在声明你的模板之后,你可以使用上面的 mixin 来扩展它们。使用以下代码,我正在扩展我的 registerlogin 模板:

    extendTemplate Template.register, loginMixin
    extendTemplate Template.login, loginMixin
    

    最后,这是我的login.html 的样子:

    <template name="login">
        <div class="alert">
            <a class="close" data-dismiss="alert" href="#">×</a>
            <h4 class="alert-heading">Merge accounts</h4>
            <form id="register_form" class="form-inline" action="#">
                <p class="help-block">Please login with {{merge_with_email}}.</p>
                <label for="email">Email:</label>
                <input id="email" type="text" class="input-medium" />
                <label for="password">Password:</label>
                <input id="password" type="password" class="input-medium" />
                <button class="btn" id="merge_login">Login</button>
            </form>
        </div>
    </template>
    

    由于我也扩展了我的register 模板,register.html 也可以使用{{merge_with_email}} 并处理merge_login 按钮的click 事件。

    【讨论】:

    • 真的很酷,但是如何运行Template.instance() 来获取帮助器中的模板?
    【解决方案4】:

    现在有了 Meteor 1.0,这似乎已经改变了。经过一番挖掘,我发现您现在可以使用以下内容在助手之间重用代码:

    https://docs.meteor.com/#/full/template_registerhelper

    Template.registerHelper("checkedIf",function(value){
      return (value)? "checked":"";
    });
    

    这使得它在所有助手中都可用!

    【讨论】:

      【解决方案5】:

      您当前的方法应该可行。更短的版本是:

      Template.foo.say_foo = 
      Template.bar.say_foo = function() { alert('foo'); };
      

      【讨论】:

        【解决方案6】:

        不确定我是否理解您的要求,但我认为您的操作没有任何问题 - 您为变量分配了一个函数以便多次重复使用它。

        如果想要减少输入或让 20 个不同的模板重用它而不是 2 个,您可以这样做:

        var templates = ['foo', 'bar', 'baz', 'barz', 'bliz', blaz'];
        for (var i=0; i < templates.length; i++) { 
            Template[templates[i]].say_foo = say_foo;
        }
        

        但 IMO 的可读性较差,没有真正需要这样做。

        编辑 - 更好的解决方案

        刚刚意识到您可能想要这样做的原因 - 确保每个模板都具有 say_foo 属性,这样您就不必担心每次创建新模板时手动添加它,您可以这样做:

        for (var t in Template)
            Template[t].say_foo = say_foo;
        

        【讨论】:

          【解决方案7】:

          在弄乱了 Gezim 的出色答案后,我意识到在 Meteor 1.3+ 中您可以简单地运行:

          Template.register.helpers(MyMixin.helpers);
          Template.register.events(MyMixin.helpers);
          

          但是如果你想要一个 extendTemplate 函数:

          // Note: above code is probably simpler.
          
          function extendTemplate(template, mixin) {
            if (mixin.helpers && template.helpers) {
              template.helpers(mixin.helpers);
            }
            if (mixin.events && template.events) {
              template.events(mixin.events);
            }
            return template;
          };
          
          extendTemplate(Template.register, {
            events: { ... },
            helpers: { ... },
          });
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-02-25
            • 1970-01-01
            • 2022-10-06
            • 1970-01-01
            • 2012-09-12
            • 2016-04-11
            • 2014-08-23
            相关资源
            最近更新 更多