当所有模板项目在 Meteor 中完成渲染时回调? [英] Callback when all Template items finished rendering in Meteor?

查看:21
本文介绍了当所有模板项目在 Meteor 中完成渲染时回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm getting a collection of records and placing them in a Template, having them rendered {{#each}} and I want to display a loading icon until the last DOM node is rendered.

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

My problem is that I have not found a way to query a state/fire a callback on the last item rendered aka the last DOM node to be updated/re-drawn.

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

It looks a bit like this in my HTML file:

<template name="stuff">
    {{#each items}}
        <div class="coolView">{{cool_stuff}}</div>
    {{/each}}
</template>

在客户端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);
};

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

The Session variable loading_stuff is queried in a Handlebars helper, returning the name of the loading class (with a loader icon GIF) if it's true.

我做这个笨拙的Meteor.setTimeout 的原因是因为Template.rendered 在每个渲染到模板的项目之后被调用.所以我需要重新确认它仍在加载,但给它一些时间来加载下一个或完成全部渲染,稍等片刻,直到将 loading_stuff 设置为 错误.

The reason I do the awkward Meteor.setTimeout is because Template.rendered is called after every single item that was rendered into the Template. So I need to re-confirm that it is still loading, but give it some time to either load the next one or to finish rendering them all, with a little pause until it sets loading_stuff to false.

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

How do I reliably query/callback at the end of all DOM updates (for a particular Template or for the whole page) the proper Meteor way?

非常感谢.

编辑

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

The solution with using the subscribe() onReady() callback only partially works:

在渲染开始之前,模板似乎被多次调用 (2-3),但是 之后 数据从模板依赖渲染的服务器返回.这意味着它已完成"加载数据,但 DOM 仍在呈现.我将尝试使用 Meteor.autorun() 并查看是否可以在某处找到可靠的钩子来正确执行此操作.与此同时,我想我原来的问题仍然存在:

Templates are seemingly called multiple (2-3) times before the rendering even starts, but after the data has returned from the server that the Template relies on to render. This means that that it's 'finished' loading data, but the DOM is still being rendered. I will play around with Meteor.autorun() and see if I can find a reliable hook somewhere to do this properly. In the meantime, I guess my original question still remains:

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

How do I know when the entire Template/page has finished rendering?

最终

归根结底,基于 DOM 的结构,开发人员有一个坚如磐石的 DOM 并尽可能将适当的回调附加到他/她想要检查其状态的元素上.这似乎是一个反气候的不费吹灰之力,但对我来说,知道模板的最终元素被渲染的唯一方法是在模板的最后渲染一个具有特殊 id 的元素,该元素表示模板的结束渲染并附加一个 .livequery 回调到它.我希望 Meteor 将来能够为检查此状态提供更加统一和全球性的支持.

At the end of the day, based on how the DOM is structured, it's up to the developer have a rock-solid DOM and attach the appropriate callbacks as best as possible to the elements he/she wants to check the state of. It may seem like an anti-climatic no-brainer, but for me the only way to know the final element of a Template is rendered is to have an element with a special id rendered at the very end of a Template that signals the end of the render and attach a .livequery callback to it. I hope that Meteor will incorporate a more unified and global support for checking this state in the future.

推荐答案

我发现在等待模板中的元素写入 DOM 时,JQuery 的 livequery 插件不起作用.这是因为该插件侦听 append 等 JQuery 方法,但 Meteor 不使用 JQuery.它使用一个名为 LiveRange 的对象来写入 DOM.我修改了我的 livequery JavaScript 文件来处理这个.

I found that JQuery's livequery plugin doesn't work when waiting for elements from a template to be written to the DOM. This is because the plugin listens on JQuery methods like append, but Meteor doesn't use JQuery. It uses an object called LiveRange to write to the DOM. I modified my livequery JavaScript file to work with this.

在文件底部附近,有一行调用 registerPlugin().我把它修改成这样:

Near the bottom of the file, there is a line that calls registerPlugin(). I modified it to look like this:

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

然后我将 registerPlugin() 方法修改为如下所示:

Then I modified the registerPlugin() method to look like this:

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;
            }
        });
    }
}

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

This will check to see if the element exists when insertBefore() or insertAfter() is called on the LiveRange object and will still work with JQuery as it did before.

这篇关于当所有模板项目在 Meteor 中完成渲染时回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆