URL解析在Meteor.startup中不起作用

时间:2013-09-21 02:43:05

标签: javascript meteor url-routing

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

2 个答案:

答案 0 :(得分:0)

如果用'Template.entergame.created'替换'Meteor.startup',这应该可行

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

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

答案 1 :(得分:0)

回答我自己的问题,因为我确实让它工作了,这可能对其他人有用。我进一步改进了笨重的用户体验,但此时,我计划取消所有这些工作,转而采用Gorb博士和emgee建议的铁路由器。如果我模拟从服务器接收数据的长时间延迟,这个解决方案就会崩溃。

问题在于发布/订阅时间线,特别是在尝试呈现相应模板之前,我需要等待订阅从服务器接收数据。

第一步是删除自动发布。

接下来,我将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之后排队这个函数的问题。)