如何在模板助手中使用 Meteor 方法

IT技术 javascript meteor
2021-01-30 16:12:14

如何定义在模板助手中也可调用的 Meteor 方法?

我有这两个文件:

文件:lib/test.js

Meteor.methods({
    viewTest : function (str) {
        return str;
    }
});

文件:客户端/myView.js

Template.helloWorld.helpers({
    txt : function () {
        var str = Meteor.call('viewTest', 'Hello World.');
        return str;
    }
});

当我给“str”一个普通字符串时,一切正常。但在这种情况下,我的模板没有任何value。我在同一个文件中定义 - 为了测试 - 在该方法是一个普通函数的地方,并试图调用该函数。我得到的错误是该函数不存在。所以我认为 Meteor 试图在它知道我为它定义的方法之前渲染模板。但我认为这有点不寻常——不是吗?

6个回答

现在有一种新方法可以做到这一点(Meteor 0.9.3.1),它不会污染 Session 命名空间

Template.helloWorld.helpers({
    txt: function () {
        return Template.instance().myAsyncValue.get();
    }
});

Template.helloWorld.created = function (){
    var self = this;
    self.myAsyncValue = new ReactiveVar("Waiting for response from server...");
    Meteor.call('getAsyncValue', function (err, asyncValue) {
        if (err)
            console.log(err);
        else 
            self.myAsyncValue.set(asyncValue);
    });
}

在“created”回调中,您创建一个 ReactiveVariable 的新实例(请参阅文档)并将其附加到模板实例。

然后你调用你的方法,当回调触发时,你将返回的值附加到react变量。

然后你可以设置你的助手来返回react变量的值(它现在附加到模板实例),它会在方法返回时重新运行。

但请注意,您必须添加reactive-var 包才能使其工作

$ meteor add reactive-var
这仍然是首选方法吗?
2021-03-16 16:12:14
@evolross op 没有要求反应式,只是方法调用的结果会更新模板。
2021-03-26 16:12:14
真的......仅供参考,以防人们认为它会自动响应,因为它使用模板助手(也许是 Meteor 的新手)。
2021-03-31 16:12:14
这不是非反应性的吗?由于ReactiveVar只有在created处理程序中更新因此,如果asyncValue更新,它不会更新您的模板,除非它刷新...?
2021-04-09 16:12:14
太好了,但是如果我要取回一个对象,我现在如何进行迭代?#each 只接受数组。我希望能够访问我的调用返回的每个对象的属性。
2021-04-10 16:12:14

Sashko添加了一个名为meteor-reactive-method的简洁小包来解决这个问题。

$ meteor add simple:reactive-method
Template.helloWorld.helpers({
  txt: function() {
    return ReactiveMethod.call('viewTest', 'Hello World.');
  }
});

正如我在常见错误中指出的那样,助手应该没有副作用,所以我会谨慎使用这种技术。但是,对于以下情况,这是一个非常方便的快捷方式:

  • 助手应该只触发一次(它不依赖于react状态)。
  • 调用的方法不会改变数据库。

您需要将返回值与 Session 变量连接起来,因为请求是异步的:

Template.helloWorld.helpers({
    txt : function () {
        return Session.get("txt") || "Loading";
    }
});

Template.helloWorld.created = function() {
    Meteor.call('viewTest', 'Hello World.', function(err, result) {
        Session.set("txt", result);
    });

}

所以 .rendered 应该在你的模板加载时调用一次(至少它应该与新版本的 Meteor 一起使用。)

该值将被调用和显示。否则它会说“正在加载”。

@TimoRütten 您是否考虑过不使用 Meteor.call 而是使用带有本地集合的转换?
2021-03-30 16:12:14
本地收藏?在我的情况下,集合的使用并不重要。问题是我必须在呈现模板之前获得返回值。也许我不明白你的问题?
2021-04-05 16:12:14
这解决了问题。但是在我的特殊情况下,这不是一个好的解决方案,因为我必须在呈现模板之前获得正确的返回值。在我的特殊情况下,我现在使用典型的 javascript 函数来解决它。你得到了“正确答案”的标记,因为它会解决它——如果它解决了我的特殊情况,这并不重要。谢谢
2021-04-08 16:12:14

客户端的方法是异步的,它们的返回值总是未定义的。要获取该方法返回的实际值,您需要提供一个回调:

Meteor.call('method', 'argument', function(error, result) {
    ....
});

现在,没有简单的方法可以在您的助手中使用结果。但是,您可以将其作为数据对象存储在模板中,然后在助手中返回:

Template.template.created = function() {
    var self = this;
    self.data.elephantDep = new Deps.Dependency();
    self.data.elephant = '';
    Meteor.call('getElephant', 'greenOne', function(error, result) {
        self.data.elephant = result;
        self.data.elephantDep.changed();
    });
};

Template.template.showElephant = function() {
    this.elephantDep.depend();
    return this.elephant;
};
是的,这对我来说适用于模板特定的依赖项。我做了类似的事情,但也用销毁来清除它们
2021-03-31 16:12:14
或者,您可以按照 Akshat 的建议使用 Session 变量,而不必担心依赖项。但是,此方法的优点是它是模板本地的。
2021-04-02 16:12:14
谢谢休伯特,我一直在寻找提供模板特定依赖项的东西。那么,如果模板被更改/加载回来,依赖关系是否也被清除了?
2021-04-06 16:12:14

这是预期的行为。您没有methods按预期使用。

您的代码viewTest在客户端上定义了一个服务器方法和一个相应的同名方法存根。

Meteor.call('viewTest', 'Hello World.');远程调用viewTest服务器并并行运行客户端上的存根。

关于存根的返回值,请参见此处的文档,特别是:

在客户端,存根的返回值被忽略。存根是为了它们的副作用而运行的:它们旨在模拟服务器方法将执行的操作的结果,但无需等待往返延迟。

关于服务器方法的返回值请看这里的文档,特别是:

在客户端,如果不传递回调并且不在存根内部,则调用将返回未定义,并且您将无法获取该方法的返回值。那是因为客户端没有纤程,所以实际上没有任何方法可以阻止方法的远程执行。