在Meteor中模板之间共享函数

15

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

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'); };

当然,模板找不到这个函数。

只是好奇最佳实践之类的。谢谢!

7个回答

17

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

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

你可以在任何模板中使用 {{my_helper}} 调用它!

希望对你有所帮助 :)


正确的方法是使用UI.registerHelper,根据Meteor文档。请参见下面的答案。 - srinivas
2
@srinivas:在 Meteor 的历史中,“正确的方式”已经发生了变化,曾经是 Handlebars,然后是 UI,现在是 Template。应该编辑原始过时的答案,而不是发布新的答案,这样会创建一个难以阅读的列表。我已经相应地更新了这个答案,因为它是第一个并且最受欢迎的答案。 - Bogdan D
@BogdanD 关于在模板之间共享函数,我认为我们仍然需要在 UI 中将其注册为一个函数,否则您将无法在模板之间共享该函数。是的,我本可以在评论中回答,但我觉得那样很难找到。 - srinivas
1
@srinivas,我的意思是编辑答案,而不是评论(我的编辑对这个答案正在等待批准,所以还没有出现在答案中)。关于UI-它已经过时了,模板取代了它。 - Bogdan D

16

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

因此,为了从任何客户端模板中访问通用函数,请在client.js中使用:

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

更新:

显然,文档已经改回使用

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

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


谢谢,我发帖时好像没有这个存在。为了让这个问题保持相关性,更改为接受的答案似乎是合适的。 - Samo
文档现在已经切换回使用Template.registerHelper - dayuloli
1
那么这就是全有还是全无的关系吗?从语义上讲,如果我创建一个子模板,我应该继承所有父模板的函数。 - Zach Smith
文档位置已更改为:http://blazejs.org/api/templates.html#Template-registerHelper - Amir Samakar

2
这是我想出来解决问题的方法,使用了CoffeeScript。如果您没有使用CoffeeScript,可以在这里将其转换为JavaScript。
首先,定义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

然后,声明一个带有helpers和events的对象(我的称为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()以在帮助程序中获取模板? - Ryan Taylor

2

Meteor 1.0已经发布,现在看来这种情况已经改变了。 经过一些探索,我发现你现在可以使用以下方法在helpers之间重复使用代码:

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

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

这使得它在所有辅助工具中都可用!

1

我不确定我是否理解你的问题,但我认为你所做的没有任何问题 - 你将一个函数分配给变量以便多次重用。

如果你想要少打一些字或者有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;
}

但在我看来,这种方法不太易读,而且没有真正的必要。

编辑 - 更好的解决方案

刚刚意识到为什么你可能想这样做 - 为了确保每个模板都有say_foo属性,这样你就不必每次创建新模板时手动添加它,你可以这样做:

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

1

你目前的方法应该是可行的。稍微更简短的版本如下:

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

0

在研究了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: { ... },
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接