问题描述
我正在获取记录的集合并将其放置在Template中,使其呈现为{{#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); };
在Handlebars帮助器中查询会话变量loading_stuff,如果它是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的原因是,在渲染到模板中的每个项目之后,被称为 .因此,我需要再次确认它仍在加载,但请给它一些时间来加载下一个或完成渲染所有内容,并稍作暂停,直到将loading_stuff设置为false.
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更新结束时(对于特定模板或整个页面)可靠地查询/回调?
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?
非常感谢.
编辑
EDIT
使用 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?
最终
FINAL
最终,根据DOM的结构,开发人员将拥有一个坚如磐石的DOM,并尽可能将适当的回调附加到他/她想要检查其状态的元素上.看起来似乎很容易,但对我而言,唯一了解Template的最终元素的方法是在Template的末尾呈现一个具有特殊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中完成渲染时回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!