javascript d3.js 和 document.onReady

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7169370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 23:10:53  来源:igfitidea点击:

d3.js and document.onReady

javascriptd3.js

提问by Roshambo

I'm just getting started with d3.jsand there is one detail which is completely eluding me: how do I have my code execute only after the DOM is ready to receive input?

我刚刚开始使用d3.js,但有一个细节让我无法理解:如何仅在 DOM 准备好接收输入后才执行我的代码?

I could, of course, use something like jQuery but that seems excessive.

当然,我可以使用 jQuery 之类的东西,但这似乎有些过分。

In every d3.js exampleI've encountered there seems to be no special document.onReady()type of routine, yet all the examples work flawlessly. When testing code on my end, however, the code totally fails if executed before the DOM is ready (throwing my code into a window.onloadconfirms this).

在我遇到的每个 d3.js 示例中,似乎没有特殊document.onReady()类型的例程,但所有示例都可以完美运行。然而,当我测试代码时,如果在 DOM 准备好之前执行代码完全失败(将我的代码放入 awindow.onload确认这一点)。

What gives?

是什么赋予了?

回答by Jon D. Koon

You'll notice in their examples that their javascript is below any of the html elements that is utilized so that part of the dom is loaded before it starts executing the javascript.

您会在他们的示例中注意到,他们的 javascript 位于任何使用的 html 元素下方,以便在开始执行 javascript 之前加载 dom 的一部分。

Simply putting your javascript at the bottom of the body is usually good enough.

简单地将您的 javascript 放在正文的底部通常就足够了。

回答by mz2

Sometimes you can't rely on the DIV / HTML element placing, for instance when you need to insert the element manipulated with D3 dynamically into the document. In such situations one solution is to monitor the document for DOMNodeInserted events and insert the D3 code in a callback (I believe this rules out IE versions prior to 9 though). Here's an example with jQuery:

有时您不能依赖 DIV/HTML 元素放置,例如当您需要将使用 D3 操作的元素动态插入到文档中时。在这种情况下,一种解决方案是监视文档中的 DOMNodeInserted 事件并在回调中插入 D3 代码(我相信这排除了 9 之前的 IE 版本)。这是一个 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");}
                 );
    }
});

回答by dehumanizer

The answer marked as correct didn't work for me, and is actually wrong. It's some kind of a hack and should not be considered as a correct answer. Same way you could just execute your code inside setTimeout(function() { .. }, 1000). It is even more reliable as you can set the delay :-/

标记为正确的答案对我不起作用,实际上是错误的。这是某种黑客行为,不应被视为正确答案。同样,您可以在 setTimeout(function() { .. }, 1000) 中执行您的代码。它更可靠,因为您可以设置延迟:-/

In my case I needed to wait for all elements to be processed in order to know their actual dimensions. When they are not built, processed and done, the numbers were not correct.

在我的例子中,我需要等待所有元素被处理才能知道它们的实际尺寸。当它们没有被建造、处理和完成时,数字是不正确的。

UPDATED.Here is the correct answer:

更新。以下是正确答案:

Most probably you get your data for building DOM using some async call like d3.json() and that's why it takes some time. As async call is non-blocking, then your subsequent code gets invoked even before the async call finishes, causing problems, and this is the reason why you posted this question.

很可能您使用诸如 d3.json() 之类的异步调用获取用于构建 DOM 的数据,这就是为什么它需要一些时间。由于异步调用是非阻塞的,因此即使在异步调用完成之前,您的后续代码也会被调用,从而导致问题,这就是您发布此问题的原因。

So you are trying to solve this by looking for something in D3 or anywhere else, that would tell you that D3 async call is finished and now you can do your next thing. Some people suggest making sync ajax call. This is awfully WRONG. Async calls are created to be async.

因此,您正试图通过在 D3 或其他任何地方查找某些内容来解决此问题,这会告诉您 D3 异步调用已完成,现在您可以做下一件事情了。有些人建议进行同步 ajax 调用。这是非常错误的。异步调用被创建为异步的。

What you actually need to do is to change your paradigm. Just pass a callback to that async call and that's it! Something like that:

你真正需要做的是改变你的范式。只需将回调传递给该异步调用即可!类似的东西:

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)
}

Also, take a look at async.js

另外,看看async.js

Binding events as suggested above is also a horrible idea. You should use .enter() .exit() instead. D3 is Data driven, if you need event-driven flow, then just use jQuery or vanilla JS!

上面建议的绑定事件也是一个可怕的想法。您应该使用 .enter() .exit() 代替。D3 是数据驱动的,如果你需要事件驱动的流程,那么就使用 jQuery 或 vanilla JS!

回答by Anonymous

You can put an onload event at body and put all d3js code in a function. For example:

您可以在 body 上放置一个 onload 事件并将所有 d3js 代码放在一个函数中。例如:

<body onload="yourFunctionName()">

And in your javascript, insert this:

在你的 javascript 中,插入:

function yourFunctionName() {
    //Your d3js code goes here
}

Just paste the full d3 example code inside this function. The onload event will happen after the DOM is ready.

只需将完整的 d3 示例代码粘贴到此函数中即可。onload 事件将在 DOM 准备好后发生。