如何确保已加载反应式DOM元素? [英] How should I make sure that a reactive DOM element has been loaded?

查看:98
本文介绍了如何确保已加载反应式DOM元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个显示图像的模板image.图像显示在canvasimg标签之间切换,具体取决于用户是刚刚创建图像还是已经在服务器上.

我使用名为pageSession的反应字典在imgcanvas之间切换,其中存储了名为displayMode的布尔反应变量.我有一个帮助器currentDisplayMode用于返回displayMode值.

所以助手看起来像这样:

Template.image.helpers({
    "currentDisplayMode" : function(){
        return pageSession.get ("displayMode");
    }
});

,然后在模板中,根据currentDisplayMode加载canvasimg,如下所示:

{{#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,该标记在我的rendereddestroyed画布模板函数上更新.

第二步是我已经用来确保在表单提交时上传文件(及其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 template rendered 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屋!

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