我剛剛開始使用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