0

我有一个函数,它接受一个字符串并根据在集合中查找文档来设置会话。在这种特殊情况下,字符串是游戏的可能名称name,我将把 Session 设置为该游戏的_id

问题是当我将它绑定到模板事件时,该函数完全按预期工作,但当我在Meteor.startup. 仅供参考-截至目前,我正在运行自动发布。(我计划在这一步之后调整发布/订阅设置。)

这是接受字符串并适当设置会话的函数:

var enterExisting = function(n) {
    var g = Games.findOne({name:n});
    var e = "That game doesn't exist.";
    Session.set("error", null);
    Session.set("no_game", null);
    if (Validation.game_exists(n)){
        Validation.clear();
        Session.set("current_game", g._id);
        window.location.hash = ("/" + n);
    } else {
        Session.set("error", e)
    }
};

在主页上,我在表单上使用此功能,它按预期工作。它设置会话、显示游戏并更改 URL。这就是它在该表单上的使用方式:

Template.entergame.events({
    'click input.enter-game': function(){
    var n = document.getElementById('enter-game-name').value;
    enterExisting(n);
}
});

当我尝试以类似的方式使用相同的功能时,Meteor.startup它不会设置会话或指导我。

Meteor.startup(function () {
    Session.set("current_game", "");
    Session.set("error", null);
    Session.set("no_game", null);
    var n = location.hash.substring(2);
    if (n.length === 0) {
        window.location.hash = "#/"
    } else {
        enterExisting(n);
    }
});

我不认为它是相关的,但以防万一这里是“加入游戏”表单的模板:

<template name="entergame">
    <div class="enter-game">
        {{#if error}}
          <p class="error bad-entry">
            {{error}} 
          </p>
        {{/if}}
        <input id="enter-game-name" type="text" placeholder="Join an Existing Game!" />
        <input type="button" class="enter-game" value="»">
    </div>
</template>
4

2 回答 2

0

回答我自己的问题,因为我确实得到了这个工作,它可能对其他人有用。我在改进笨重的 UX 方面又迈出了一小步,但此时,我计划按照 Gorb 博士和工程师的建议删除所有这些工作,转而使用 Iron Router。如果我模拟从服务器接收数据的长时间延迟,此解决方案将失效。

问题在于发布/订阅时间线,具体来说,我需要等待订阅从服务器接收数据,然后再尝试呈现适当的模板。

第一步是删除自动发布。

接下来,我将 URL 解析函数放入回调中,如下所示:

Meteor.startup(function () {
    Session.set("current_game", "");
    Session.set("error", null);
    Session.set("no_game", null);
    var n = location.hash.substring(2);
    Meteor.subscribe("dice");
    Meteor.subscribe("games", function(){
        if (n.length === 0) {
        window.location.hash = "#/"
        $('.home').fadeIn('slow');
        } else {
        enterExisting(n);
        setTimeout(function(){$('.currentgame').fadeIn('slow')}, 1);
    }});
});

这只是确定订阅返回数据后要加载哪个模板的回调:

    Meteor.subscribe("games", function(){
        if (n.length === 0) {
        window.location.hash = "#/"
        $('.home').fadeIn('slow');
        } else {
        enterExisting(n);
        setTimeout(function(){$('.currentgame').fadeIn('slow')}, 1);
    }});

有了这个解决方案,回调函数可能 可能会在页面加载后发生,一旦加载数据就会突然切换模板。所以我添加了一个简单的解决方案:当它准备好时,在正确的模板中隐藏可能改变和淡出的部分。

在我的 CSS 中:

.home, .currentgame {display:none;}

在上面的 JS 中,你会看到:

    Meteor.subscribe("games", function(){
        .
        .
        .
        $('.home').fadeIn('slow');
        .
        .
        .
        setTimeout(function(){$('.currentgame').fadeIn('slow')}, 1);
    }});

至于setTimeout,我真的没有解释,但它得到了它的工作。(我怀疑这是在 Session.set 东西后面对该函数进行排队的问题。)

于 2013-09-23T00:32:03.713 回答
0

如果您将“Meteor.startup”替换为“Template.entergame.created”,这应该可以工作

'Meteor.startup' 用于服务器,不会在每次渲染模板时执行。这就是为什么每个模板都有一个“已创建”事件。

emgee 是对的:您应该使用iron-router进行客户端路由(目前没有服务器端)。尤其如此,因为 Iron-router 允许您在渲染时为模板设置默认数据。

于 2013-09-22T08:15:52.250 回答