2013-04-08 24 views
23

我需要精確測量我的web應用程序,這我通過創建一個元素(相關CSS類)實現中的文本的尺寸,並設置其innerHTML然後將其添加到容器使用appendChild如何分辨時動態創建的元素已呈現

這樣做了以後,有一個等待的元素被渲染前和offsetWidth可以讀找出文本有多寬。

目前,我使用setTimeout(processText, 100)等到渲染完成。

有任何回調,我可以聽,或者當我創建的元素已經被渲染講的更可靠的方法?

+1

如果有人發現這個問題,可以在這裏找到很好的答案http://stackoverflow.com/a/5629730/697388和這裏http://stackoverflow.com/a/850995/697388 – 2013-04-23 08:25:54

+0

可能的重複[如何檢查元素是否存在於可見的DOM?](http://stackoverflow.com/questions/5629684/how-to-check-if-element-exists-in-the-visible-dom) – iConnor 2013-09-15 16:13:05

+0

可能重複[Is可以確定何時使用JavaScript呈現元素?](http://stackoverflow.com/questions/3667991/is-is-possible-to-determine-when-an-element-has-been-rendered-using -javascript) – Purefan 2014-01-10 11:25:07

回答

29

目前指示的元件已被完全呈現沒有DOM事件(例如,施加附加CSS和繪製)。這可以使一些DOM操作代碼返回錯誤或隨機結果(如獲取元素的高度)。

使用setTimeout爲瀏覽器提供一些渲染開銷是最簡單的方法。使用

setTimeout(function(){}, 0) 

也許是最實際準確的,因爲它使你的代碼在活動的瀏覽器事件隊列中沒有任何其它延遲結束 - 換句話說,你的代碼是渲染操作之後排隊(和所有其他當時正在進行的操作)。

+1

值得指出,有時候你需要在一段時間內通過。我嘗試獲取容器的滾動高度時遇到了問題,該屬性有時爲0,有時是正確的。增加一個500毫秒的延遲來抓住這個屬性解決了這個問題。 – markthewizard1234 2017-11-24 15:16:44

+0

聽起來像你正在做的不止一個重繪,@ markthewizard1234。 – mystrdat 2017-11-29 14:38:45

5

This blog post由Swizec Teller建議使用​​並檢查元素的size

function try() { 
    if (!$("#element").size()) { 
     window.requestAnimationFrame(try); 
    } else { 
     $("#element").do_some_stuff(); 
    } 
}; 
在實踐

它永遠只重試一次。因爲無論如何,在下一個渲染幀中,無論是在60秒還是一分鐘內,該元素都將被渲染。

0

當您例如

var clonedForm = $('#empty_form_to_clone').clone(true)[0]; 

var newForm = $(clonedForm).html().replace(/__prefix__/g, next_index_id_form); 

// next_index_id_form is just a integer 

我在做什麼嗎?
我克隆已經渲染的元素並更改要呈現的html。

接下來我將該文本追加到容器中。

$('#container_id').append(newForm); 

問題是當我想要一個事件處理程序添加到裏面newForm按鈕,WELL,只需使用準備事件。

$(clonedForm).ready(function(event){ 
    addEventHandlerToFormButton(); 
}) 

我希望這對你有所幫助。

PS:對不起,我的英語。

3

接受的答案是從2014年開始,現在已過時。 A setTimeout可以工作,但它不是最乾淨的,它不一定保證該元素已被添加到DOM。

今天,您應該使用MutationObserver來檢測元素何時添加到DOM。 MutationObservers現在在所有現代瀏覽器(Chrome 26 +,Firefox 14 +,IE11,Edge,Opera 15 +等)中得到廣泛支持。

將元素添加到DOM後,您將能夠檢索其實際尺寸。

下面是一個簡單示例,說明如何使用MutationObserver來監聽元素何時添加到DOM。

爲簡潔起見,我使用jQuery語法構建節點並將其插入到DOM中。

var myElement = $("<div>hello world</div>")[0]; 

var observer = new MutationObserver(function(mutations) { 
    if (document.contains(myElement)) { 
     console.log("It's in the DOM!"); 
     observer.disconnect(); 
    } 
}); 

observer.observe(document, {attributes: false, childList: true, characterData: false, subtree:true}); 

$("body").append(myElement); // console.log: It's in the DOM! 

observer事件處理程序將觸發每當任何節點被添加或從document除去。在處理程序內部,我們然後執行contains檢查以確定myElement現在是否在document中。

因爲您可以直接在myElement上執行document.contains檢查,所以不需要遍歷存儲在mutations中的每個MutationRecord。

要提高性能,請將document替換爲DOM中包含myElement的特定元素。

+0

這在文本呈現的情況下不起作用。 – 2018-03-06 16:24:50

+0

@ErikGrosskurth document.contains也適用於'TextNode'。下面是一個例子:jsfiddle.net/ef9yub3y但根據MDN,它可能不適用於較舊的IE。如果您的實施遇到問題,請隨時在SO上發佈,我很樂意看一看。 – 2018-03-06 18:00:22

+0

帶文本的東西是呈現dom元素,然後文本進一步改變觀察者已經輸入到if語句中的哪些內容,以便觀察者保持初始快照。它可能只是一個鍍鉻的東西。不確定 – 2018-03-06 19:32:00