2015-10-07 144 views
0

是否有任何其他方法可以在不使用scrollHeight的情況下獲取某個HTML元素的內部高度?scrollHeight的替代DOM屬性

事情是我有一個有100個記錄的表格,在每個記錄中,我使用height = 0然後height = scrollHeight在列中調整某個textarea的大小。

問題是IE執行scrollHeight至少20〜50ms取決於大小和我有大約100條記錄。這意味着,僅僅爲了IE來渲染所有的記錄,只需要加載100條記錄需要6秒以上,如果我需要加載100條記錄呢?那會毀了我的網站。

所以我問是否有任何替代scrollHeight或者你可以提供任何替代代碼,調整textarea。

謝謝你是進步,

UPDATE

這是我從IE瀏覽器用戶界面的響應得到 enter image description here

更新2

二圖片:正如你所看到的下面的圖片,爲什麼IE在獲取某個元素的scrollHeight方面很慢ENT(文本區域),是因爲它計算整個佈局(HTML正文),而不是隻讓特定元素的scrollHeight屬性(textarea元素)

enter image description here

回答

4

這聽起來像你再逐行,閱讀scrollHeight然後設置height。這是非常昂貴的,因爲在寫入之後每次讀取都會觸發重排,以便給出準確答案(因爲寫入可能會改變頁面上會影響正在讀取的值的內容)。這不是height=scrollHeight需要時間;這是爲了做到這一點所必需的迴流。

layout (write height of all: 0) 

reflow 
read scrollHeight 
write height 

reflow (!) 
read scrollHeight 
write height 

reflow (!) 
read scrollHeight 
write height 
... 

reflow (!) 
paint 

(或者你設置height爲0在每次迭代中,它並不重要,因爲連續寫入無法觸發迴流。)

相反,嘗試做一個批次。將所有的scrollHeight值讀入一個數組;那麼,當你擁有他們全部時,把他們全部設置好。這樣,你將只會得到兩次重排:一次當你開始閱讀時,一次當你完成你的代碼並且瀏覽器需要顯示頁面時,因爲只要你只是閱讀或者只是寫作,沒有迴流是隻有當你從寫作到閱讀價值時才需要。

layout (write height of all: 0) 

reflow 
read scrollHeight 
read scrollHeight 
... 
write height 
write height 

reflow 
paint 

編輯:這是一個黑客;我還沒有那麼好的Knockout。但作爲一個可能的最小例子,如果你不能以任何其他方式做,它可能會這樣做。你可能會想運行它,並延伸到「整頁」,否則您將無法看到任何東西:)

var vm = { 
 
    list: ko.observableArray(["foo", "bar\nbaz", "1\n2\n3\n4"]) 
 
}; 
 

 
var updatedHeights; 
 

 
ko.bindingHandlers.autoresizeStart = { 
 
    update: function(elem, valueAccessor) { 
 
    var data = ko.utils.unwrapObservable(valueAccessor()); 
 
    console.log("start update; setting updateHeights to []"); 
 
    updatedHeights = []; 
 
    } 
 
}; 
 
ko.bindingHandlers.autoresize = { 
 
    update: function(elem, valueAccessor) { 
 
    console.log("mid update;", elem, "is updated, so let's remember its scrollHeight"); 
 
    updatedHeights.push([elem, elem.scrollHeight]); 
 
    } 
 
}; 
 
ko.bindingHandlers.autoresizeEnd = { 
 
    update: function(elem, valueAccessor) { 
 
    var data = ko.utils.unwrapObservable(valueAccessor()); 
 
    console.log("end update; lets set heights for all updated elements:"); 
 
    updatedHeights.forEach(function(elemWithHeight) { 
 
     console.log(" ", elemWithHeight[1], elemWithHeight[0]); 
 
     elemWithHeight[0].style.height = elemWithHeight[1] + "px"; 
 
    }); 
 
    console.log("all done :)"); 
 
    } 
 
}; 
 

 
ko.virtualElements.allowedBindings.autoresizeStart = true; 
 
ko.virtualElements.allowedBindings.autoresizeEnd = true; 
 

 

 
ko.applyBindings(vm); 
 

 
setTimeout(function() { 
 
    vm.list.push("a\nb\nc\nd\ne\nf\ng"); 
 
}, 1000);
<!-- results pane console output; see http://meta.stackexchange.com/a/242491 --> 
 
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script> 
 

 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script> 
 

 
<!-- ko autoresizeStart: list --><!-- /ko --> 
 
<ul data-bind="foreach: list"> 
 
    <li > 
 
    <textarea data-bind="text: $data, autoresize: $data"></textarea> 
 
    </li> 
 
</ul> 
 
<!-- ko autoresizeEnd: list --><!-- /ko -->

+0

它也許可能,但事情是,我使用淘汰賽JS。然後我創建了一個autoResizeHeight自定義綁定。我的記錄在一個Items()observableArray屬性中。所以它會實際循環每個項目。 – VJPPaz

+0

檢查我的更新,基於截圖。我有2個單獨的電話爲scrollHeight,但第二個電話毫秒離我的第一個電話執行時間不是很遠 – VJPPaz

+0

因此,模式是我預測 - 你有'style.height = 0'(寫),然後是'scrollHeight' (一讀)。這觸發迴流。我不知道如何用你的自定義綁定解決這個問題,但基本上你會想要兩次遍歷:一個是將所有元素的高度渲染爲零,然後當它們全部渲染時,將它們全部設置爲scrollHeight。 – Amadan