如何确保已加载反应式DOM元素? [英] How should I make sure that a reactive DOM element has been loaded?
问题描述
我有一个显示图像的模板image
.图像显示在canvas
和img
标签之间切换,具体取决于用户是刚刚创建图像还是已经在服务器上.
我使用名为pageSession
的反应字典在img
和canvas
之间切换,其中存储了名为displayMode
的布尔反应变量.我有一个帮助器currentDisplayMode
用于返回displayMode
值.
所以助手看起来像这样:
Template.image.helpers({
"currentDisplayMode" : function(){
return pageSession.get ("displayMode");
}
});
,然后在模板中,根据currentDisplayMode
加载canvas
或img
,如下所示:
{{#if currentDisplayMode}}
<img src="{{source}}"width="215" height="215"/>
{{else}}
<canvas id="canvas" width="215" height="215"></canvas>
{{/if}}
1.问题.
如果我尝试这样的事情:
pageSession.set("displayMode", false)
var canvas = template.find('#canvas')
//do stuff related to canvas
我找不到画布,因为UI尚未更新.
2.我的肮脏修补程序
我使用Meteor.setTimeout()
这样修复它:
pageSession.set("displayMode", false)
Meteor.setTimeout(function(){
var canvas = template.find('#canvas')
//do stuff related to canvas
}, 100);
3.我的问题
到目前为止,此修复程序有效,但是我担心100ms不足以更新UI的情况.而且,我觉得这不是一个可靠的解决方案.
请注意,它不仅仅是二进制切换(图像或画布).需要根据3种不同的模式(identicon,photo,imageFile)重新渲染画布.每种模式也可以重新渲染.
总结起来,我需要在几种情况下正确填充画布(一旦确定画布已经渲染过):
- 当
displayMode
切换时:从<c14>到<canvas>
- 当我用另一种方法填充画布时:例如从identicon到照片
- 当我用相同的方法填充画布但使用不同的数据时:我重新加载了另一个identicon或我加载了另一张照片. 您将如何进行?
我尝试了另外两种方法,都将画布移动到专用模板中:
-
Blaze.render()
目标div中的模板,并附加到画布模板rendered
函数我的代码.这使得很难控制加载了什么或加载了什么:我需要删除以前渲染的画布模板. - 解决方法在此处说明:流星:强制重新渲染使用Blaze更新集合后的整个模板也不起作用(我没有努力,它看起来不是一个干净的解决方法).
我终于设法解决了这个问题.基本上,我要确保在执行我的3个填充任务(identicon,photo,imageFile)之一之前,已渲染画布.
第一步很简单:我使用页面会话反应变量标记canvasLoaded
,该标记在我的rendered
和destroyed
画布模板函数上更新.
第二步是我已经用来确保在表单提交时上传文件(及其URL可用)的步骤.这是我在这里找到的waitfor
函数: https://stackoverflow.com/a/14811679/3793161 >
所以我要做的是等待waitfor
函数中的标志canvasLoaded
切换为true.在waitfor
的回调中,我只调用一个loadCanvas
函数,根据当前的填充模式和参数(全部存储在反应式字典变量中),在其中加载画布.
等等! :-)
I have a template image
where I display images. The image display toggles between canvas
and img
tags, depending on if the user just created the image or if it is already on server.
I toogle between img
and canvas
using a reactive dictionary called pageSession
where I store a boolean reactive variable called displayMode
. I have an helper currentDisplayMode
used to return displayMode
value.
So the helper looks like this:
Template.image.helpers({
"currentDisplayMode" : function(){
return pageSession.get ("displayMode");
}
});
and in my template, I load the canvas
or the img
depending on currentDisplayMode
like this:
{{#if currentDisplayMode}}
<img src="{{source}}"width="215" height="215"/>
{{else}}
<canvas id="canvas" width="215" height="215"></canvas>
{{/if}}
1. the problem.
If I try something like this:
pageSession.set("displayMode", false)
var canvas = template.find('#canvas')
//do stuff related to canvas
I can't find my canvas because the UI isn't updated yet.
2. My dirty fix
I use a Meteor.setTimeout()
like this to fix it:
pageSession.set("displayMode", false)
Meteor.setTimeout(function(){
var canvas = template.find('#canvas')
//do stuff related to canvas
}, 100);
3. My question
This fix works so far but I'm worried about cases where 100ms wouldn't be enough to update the UI. Moreover, I don't feel like it is a reliable solution.
Note that it is not just a binary toggle (image or canvas). The canvas need to be re-rendered depending on 3 different modes (identicon, photo, imageFile). Each mode can be re-rendered as well.
To sum it up, I need to fill properly my canvas in several cases (once I make sure it has been rendered before):
- when
displayMode
toogles: from<img>
to<canvas>
- when I fill my canvas with another method: from identicon to photo for instance
- when I fill my canvas with the same method, but different data: e.g. I reload another identicon or I load another photo. How would you proceed?
I tried two other approaches, both by moving the canvas into a dedicated template:
Blaze.render()
the template in a target div and attach to the canvas templaterendered
function my code. It makes it difficult to control what is or what isn't loaded: I need to remove previously rendered canvas templates.- the workaround explained here: Meteor: Forcing rerendering whole template after collection update with Blaze did not work either (I haven't tried hard, it does not look like a clean workaround).
I finally managed to solve this. Basically, what I wanted was to be sure that my canvas was rendered before doing one of my 3 filling tasks (identicon, photo, imageFile).
The first step is the easy one: I use a page Session reactive variable flag canvasLoaded
that I update on my rendered
and destroyed
canvas template functions.
The second step is something I already used to make sure a file was uploaded (and its url available) on form submit. This is a waitfor
function I found here : https://stackoverflow.com/a/14811679/3793161
So what I do is to wait for my flag canvasLoaded
to switch to true in the waitfor
function. In the callback of waitfor
I just call a loadCanvas
function where I load the canvas according to the current filling mode and parameters (all stored in reactive dictionary variables).
Et voilà! :-)
这篇关于如何确保已加载反应式DOM元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!