我刚刚开始使用d3.js,并且有一个细节完全避开了我:只有在DOM准备好接收输入后,我如何才能让代码执行?d3.js和document.onReady
我当然可以使用类似jQuery的东西,但看起来过多。
在every d3.js example我遇到过似乎没有特殊的document.onReady()
类型的例程,但所有的例子工作完美无瑕。然而,当在我的端测试代码时,如果在DOM准备好之前执行代码,则代码完全失败(将我的代码投入window.onload
证实了这一点)。
什么给?
我刚刚开始使用d3.js,并且有一个细节完全避开了我:只有在DOM准备好接收输入后,我如何才能让代码执行?d3.js和document.onReady
我当然可以使用类似jQuery的东西,但看起来过多。
在every d3.js example我遇到过似乎没有特殊的document.onReady()
类型的例程,但所有的例子工作完美无瑕。然而,当在我的端测试代码时,如果在DOM准备好之前执行代码,则代码完全失败(将我的代码投入window.onload
证实了这一点)。
什么给?
你会发现在他们的例子中,他们的javascript低于任何html元素,因此在开始执行javascript之前,部分dom被加载。
简单地把你的JavaScript放在身体的底部通常是足够好的。
有时你不能依赖DIV/HTML元素放置,例如当你需要将使用D3操作的元素动态地插入到文档中时。在这种情况下,一种解决方案是监视文档中的DOMNodeInserted事件,并在回调中插入D3代码(我相信这排除了IE版本在9之前)。下面是使用jQuery的例子:
$(document).bind('DOMNodeInserted', function(event)
{
if (event.target.id == "viz")
{
var sampleSVG = d3.select("#viz")
.append("svg:svg")
.attr("width", 100)
.attr("height", 100);
sampleSVG.append("svg:circle")
.style("stroke", "gray")
.style("fill", "white")
.attr("r", 40)
.attr("cx", 50)
.attr("cy", 50)
.on("mouseover", function() {
d3.select(this).style("fill", "aliceblue");
})
.on("mouseout", function() {
d3.select(this).style("fill", "white");}
);
}
});
您可以在体内把onload事件,并把所有d3js代码的功能。例如:
<body onload="yourFunctionName()">
而在你的JavaScript中,插入此:
function yourFunctionName() {
//Your d3js code goes here
}
只需粘贴在这个函数内全D3示例代码。 onload事件将在DOM准备就绪后发生。
为了测试的目的,这很好,但请注意设置'body.onload'通常被认为是不好的形式,因为其他脚本可以覆盖它。 'addEventListener'比较好,但与'document.onReady'相比还是有点慢。 – Roshambo
标记为正确的答案不适用于我,实际上是错误的。这是一种黑客行为,不应被视为正确的答案。同样,你可以在setTimeout(function(){..},1000)内执行你的代码。它更可靠,因为你可以设置延迟: -/
在我的情况下,我需要等待所有元素进行处理,以了解他们的实际尺寸。当它们不被构建,处理和完成时,数字是不正确的。
已更新。这里是正确的答案:
很可能你会用d3.json()这样的异步调用来获得构建DOM的数据,这就是为什么它需要一些时间。由于异步调用是非阻塞的,因此即使在异步调用完成之前,您的后续代码也会被调用,从而导致问题,这就是您发布此问题的原因。
所以你试图通过在D3或其他任何地方寻找东西来解决这个问题,那会告诉你D3异步调用已经完成,现在你可以做下一件事了。有人建议做同步ajax调用。这是非常错误的。异步调用被创建为异步。
你实际需要做的是改变你的范例。只需将回调传递给该异步调用即可!类似的东西:
function thingsToDoWhenDOMisBuilt() {
...
}
function buildDOM(rootNode, error, thingsToDoWhenDOMisBuilt) {
...
// everything is built, so we can do our post-build thing against DOM
if (thingsToDoWhenDOMisBuilt)
thingsToDoWhenDOMisBuilt()
}
d3.json(urlToData, buildDOM) {
if (error)
console.log("oops")
buildDOM(rootNode, thingsToDoWhenDOMisBuilt)
}
而且,上述建议在async.js
绑定事件看一看也是一个可怕的想法。您应该使用.enter().exit()代替。 D3是数据驱动的,如果你需要事件驱动的流程,那么只需使用jQuery或者vanilla JS!
辉煌,谢谢。显然,我一直在jQuery土地太久。 – Roshambo
这是不好的做法,为什么jQuery及其竞争对手中有这么多的已有变体。 – ijw
ilw是对的。在某些移动WebViews上,它有时会在打开应用程序时报告不正确的屏幕宽度大小。在准备等待文件避免了这一点。 – phreakhead