有没有比$(document).ready()更可靠的东西?

5
我有一个实用程序,可以绘制简单的弧形,可以使用SVG或Canvas作为回退选项。(早期版本可在我的网站Raphael Arcs Project中找到。)
为了适应移动解决方案,我最近添加了监视容器大小的代码,如果它发生变化,则重新绘制图像以适应新的大小容器。此添加仅使用包含DIV的大小;代码将SVG或Canvas对象添加到DIV中。
但是,重复加载页面时,即使$(document).ready显示已准备就绪,DIV布局有时也没有准备好。这似乎在Chrome下最为普遍;我只在Opera中看到过一次,在Firefox 3.6中从未见过。包含DIV的高度和宽度返回为零。
如果在Chrome中加载上面的链接并点击重新加载,每隔十次左右,Canvas演示文稿都会显示类似的缺陷:它将被调整为视口的宽度:100%,高度:300px,并且演示文稿不会正确绘制。
我查看了jQuery文档,它似乎坚持认为$(document).ready()足够了。我希望不要让12%的用户经历与浏览器相关的故障。除了编写自己的布局探针(一个旋转的超时不停地询问"容器是否已经调整大小了?" ),还有没有通用的技术或库来确保不仅DOM已加载而且布局管理器已经解决了呢?
[编辑]
我最终做了这样的事情(代码是Coffeescript):
$(document).ready ->
    $('.wrapper').each ->
        demo = =>
            c = new CanvasArc $('.canvas_demo', this)
            c.sweep(1.0)
            r = new RaphaelArc $('.raphael_demo', this)
            r.sweep(1.0)
        scan = =>
            if $('.canvas_demo', this).height()
                demo()
            else
                setTimeout(scan, 100)
        scan()

我真的不应该这样做。


3
window.onload.ready 不会等待图片加载。 - Raynos
@Raynos - 你应该把那个发表为一个答案。 - JasCav
@JasCav 但是如果你仔细阅读他的实际问题,他实际上是在询问等待canvas/svg加载完成,这与图像不同。我不知道.onload是否适用于修复canvas/svg。 - Raynos
@Raynos - 噢...好观点。我阅读理解失败了。 :-p - JasCav
并不是这样。问题在于我想要添加一个<canvas>或<svg>标签的DIV尚未被调整大小,即使.ready已经触发,这导致绘图表面具有零尺寸。 - Elf Sternberg
@ElfSternberg 我的意思是 onload 事件会在 ready 事件之后触发。尝试使用 onload 事件来解决你的问题。或者检测 <div> 元素的 load 事件,但这种方法在浏览器支持方面存在问题。 - Raynos
4个回答

6
您说得对,您不应该绕过这个问题。答案隐藏在.ready()部分中:.ready() section
引用: 当使用依赖于CSS样式属性值的脚本时,重要的是在引用脚本之前引用外部样式表或嵌入样式元素。
所以您需要做的就是先包含CSS,然后再包含脚本。这样,即使在CSS加载完成之前,您的ready事件处理程序也不会被设置。

不幸的是,这似乎起作用了;将样式表的<link>标签放在<script>标签之上似乎让Chrome的问题消失了。这完全没有任何意义,但我接受它。 - Elf Sternberg
4
这是世界上最有意义的事情。在检查它们的高度之前,需要知道如何绘制物体。一般规则是最后加载脚本。 - Levi Morrison
此外,许多人建议将<script>标签放在页脚中,以加快页面加载速度。 - Kalessin
浏览器在告诉你样式化元素的尺寸之前必须先应用你的样式。因此,请先加载你的样式! :) - sam

1
整个 $(document).ready 的意义在于它会在 DOM 准备好进行操作时立即触发,而不必等待所有图像下载完成。如果您需要图像已下载,请附加到常规的 onload 事件。如果您正在动态添加图像,则可以 附加到 Image 对象的 onload 事件 然后执行一些操作。

Nick,我不是在下载图片。我正在使用Canvas和SVG来渲染图表、图形和其他矢量艺术,使用已经存在于DOM中的数据。 - Elf Sternberg

1

ready 是一个事件,表示 DOM 已经准备好进行脚本编写了——也就是说,所有元素都具有基本属性,您可以添加/删除元素等——但并不意味着所有元素都已呈现。如果您希望确保所有“已加载资源”完全完成加载所有内容(包括需要加载时间的图像和可能的其他嵌入式内容),请使用 window.onload (load 在 jQuery 中)。

jQuery 的 ready 页面 说:

对于依赖于已加载资源的代码,在处理程序中应将其放置在 load 事件中。

您正在查看的 div 的任何内容都是“已加载的资产”吗?如果是这样,那么在 ready 事件之后它们的加载可能会改变 div 的大小。理论上,您应该能够使用 asset.load 来在特定的已加载资产完成下载时立即响应。使用 document.ready 来连接此事件。


正如已经提到的,我不会下载图像。这与 IMG 标记无关,而与 CANVAS 和 SVG 标记有关。我同意它们应该在“准备就绪”时以其基本属性存在,包括高度和宽度。但在 Chrome 中,这并不总是发生。 - Elf Sternberg
@Elf,ErikE说:“但不是所有元素都已经渲染。”如果元素尚未呈现,我不会期望设置宽度和高度。请尝试使用window.onload - David

0

您不应该依赖脚本来调整

的大小,而是应该通过CSS让它以百分比宽度自适应大小,这样在文档准备就绪时它就已经被调整好了。


DIV的大小是通过CSS设置的。由于我不知道浏览器的能力,所以必须等到.ready来确定能力(我正在使用Modernizr),然后将CANVAS或SVG添加到DIV中,使用DIV的大小来设置绘图表面的大小。尽管使用CSS设置了大小,但有时在.ready触发后仍会出现高度、宽度为0的情况。 - Elf Sternberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接