当所有模板项目在Meteor中完成渲染时回调?

cne*_*uro 6 publish-subscribe meteor

我正在获取一组记录并将它们放在一个模板中,让它们渲染{{#each}},我想显示一个加载图标,直到最后一个DOM节点被渲染.

我的问题是我还没有找到一种方法来查询状态/触发最后一个项目的回调,也就是要更新/重新绘制的最后一个DOM节点.

在我的HTML文件中看起来有点像这样:

<template name="stuff">
    {{#each items}}
        <div class="coolView">{{cool_stuff}}</div>
    {{/each}}
</template>
Run Code Online (Sandbox Code Playgroud)

在客户端JS文件中:

// returns all records of Stuff belonging to the currently logged-in user
Template.stuff.items = function () {
    Session.set('loading_stuff', true);
    return Items.find({owner: Meteor.userId()}, {sort: {created_time: -1}});
};

Template.stuff.rendered = function() {
    // every time something new is rendered, there will have been loading of the DOM. 
    // wait a short while after the last render to clear any loading indication.
    Session.set('loading_stuff', true);
    Meteor.setTimeout(function() {Session.set('loading_stuff', false);}, 300);
};
Run Code Online (Sandbox Code Playgroud)

loading_stuff在Handlebars帮助器中查询Session变量,如果是,则返回加载类的名称(带有加载器图标GIF)true.

我做尴尬的原因Meteor.setTimeout是因为在每个渲染到模板中的项目之后Template.rendered调用.所以我需要重新确认它仍在加载,但是给它一些时间来加载下一个或者完成全部渲染,稍稍暂停直到它设置为.loading_stufffalse

如何在所有DOM更新结束时(针对特定模板或整个页面)可靠地查询/回调正确的Meteor方式?

非常感谢.

编辑

使用回调的解决方案仅部分工作:subscribe() onReady()

模板在渲染甚至开始之前似乎被称为多次(2-3)次,但是从服务器返回数据之后,模板依赖于渲染.这意味着它已经"完成"加载数据,但DOM仍在呈现中.我会玩,Meteor.autorun()并看看我是否可以找到一个可靠的钩子来正确地做到这一点.与此同时,我想我的原始问题仍然存在:

我如何知道整个模板/页面何时完成渲染?

最终编辑:

在一天结束时,根据DOM的结构,开发人员可以拥有一个坚如磐石的DOM,并尽可能地将适当的回调附加到他/她想要检查状态的元素上.它可能看起来像一个反气候的脑子,但对我来说,知道模板的最终元素的唯一方法是渲染一个元素,在模板的最末端呈现一个特殊的id,表示结束渲染并附加一个.livequery回调.我希望Meteor将来会更加统一和全球支持检查这个状态.

小智 6

将项目模板嵌套在当前模板中可能实际上有帮助吗?

<template name="stuff">
   {{#each items}}
     {{> itemTemplate}}
   {{/each}}
</template>

<template name="itemTemplate">
   <div class="coolView">{{cool_stuff}}</div>
</template>
Run Code Online (Sandbox Code Playgroud)

现在每次将新项更新到DOM时,Template.itemTemplate.rendered上的回调都可以运行.


Irv*_*ing 4

我发现 JQuery 的 livequery 插件在等待模板中的元素写入 DOM 时不起作用。这是因为该插件侦听 JQuery 方法(如追加),但 Meteor 不使用 JQuery。它使用一个被调用的对象LiveRange来写入 DOM。我修改了我的 livequery JavaScript 文件来处理这个问题。

在文件底部附近,有一行调用registerPlugin(). 我将其修改为如下所示:

$.livequery.registerPlugin([
    {object: $.fn, methods: ['append', 'prepend', 'after', 'before', 'wrap', 'attr',    'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html']},
    {object: LiveRange.prototype, methods: ['insertBefore', 'insertAfter']} 
]);
Run Code Online (Sandbox Code Playgroud)

然后我修改了 registerPlugin() 方法,如下所示:

registerPlugin: function(registration) {
    for (var i = 0; i < registration.length; i++) {
        var object = registration[i].object;
        var methods = registration[i].methods;

        $.each( methods, function(i,n) {
            // Short-circuit if the method doesn't exist
            if (!object[n]) return;

            // Save a reference to the original method
            var old = object[n];

            // Create a new method
            object[n] = function() {
                // Call the original method
                var r = old.apply(this, arguments);

                // Request a run of the Live Queries
                $.livequery.run();

                // Return the original methods result
                return r;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这将检查在对象上调用insertBefore()或时元素是否存在,并且仍然像以前一样使用 JQuery。insertAfter()LiveRange