流星:在“渲染”中加载集合'功能

时间:2014-03-28 15:54:49

标签: javascript meteor

在我的Meteor应用程序中,我有这个rendered功能,需要访问特定的集合。假设我有一个ToDos集合

ToDos = new Meteor.Collection('todos');

if (Meteor.isClient) {
    Meteor.subscribe('todos');
}

if (Meteor.isServer) {
    Meteor.startup(function () {
        Meteor.publish('todos', function () {
            return ToDos.find({});
        });
    });
}

现在在渲染函数中我想做类似这样的事情

Template.todos.rendered = function () {
    var todo = ToDos.findOne({...});

    if (todo) {
        $('[datepicker]').datepicker('setDate', todo.date);
    }
}

我遇到的问题是,当调用rendered时,todoundefined,此函数仅调用一次。有没有解决这个问题? Deps.autorun能帮忙吗?如果是,怎么样?

另一方面,如果我只能听ToDos,我可以在那里更新日期选择器!

2 个答案:

答案 0 :(得分:1)

是的,这是Meteor中一个可能令人讨厌的问题。基本上,虽然Meteor.subscribe调用返回的句柄有ready方法,它会告诉您集合是否准备就绪,通常您的rendered回调将在返回时运行true,所以在这种情况下它不是很有用。在某些情况下,您可以在订阅中使用onReady回调,如果您知道模板实例存在并且可以执行任何操作,甚至可以从其他地方插入模板的数据上下文可能在rendered回调中,但这可能是处理你出现的问题的一种非常混乱的方式(因为如果在DOM之前有一个集合 准备好的情况已被渲染它会掉下来。)

<强>解: 通常情况下,iron router是最好的解决方案,因为它允许每个路由都有waitOn回调,您可以使用它来指定哪些订阅需要ready()之前页面开始呈现(尽管您可以等待ready回调的任何内容,而不仅仅是订阅)。这样,您始终知道,Collection.find会在您的rendered首次回调运行时返回您期望的内容。

答案 1 :(得分:1)

假设您有一个只有一页的简单应用

使用deps的可能实现

if (Meteor.isClient) {
    Meteor.startup(function() {
        Meteor.subscribe('todos');
        Deps.autorun(function(e) {
            var todo = ToDos.findOne({...});
            var $picker = $('[datepicker]');
            if (!!todo && !!$picker) {
                $picker.datepicker('setDate', todo.date);
            }
        });
    });
}

Meteor首先渲染模板,然后抓取数据。因此,当数据发生变化时,您必须设置数据选择器。

Collection.observe也可能对您感兴趣。每次添加,更改,删除数据等时都可以进行回调。

var todo = ToDos.find({...});
var handle = todo.observeChanges({
    added: function (id, todo) {
        // do stuff on added
    },
    removed: function () {
        // do stuff on removed
    }
});