2017-03-28 19 views
0

我試圖「保留」DOM的子樹供以後使用和重新基於一些用戶操作(我最初創建和使用DocumentFragment操作,然後附加到DOM的子樹),但我沒有想要追加並隱藏在DOM的某個地方,因爲對它的進一步(並且在我的情況下很沉重)操作比較慢,並且導致佈局迴流和進一步的性能影響。如何將DOM的子樹轉換爲DocumentFragment?

是否有一個跨瀏覽器的方式(我關心的IE11 +)將一些DOM子樹轉換回DocumentFragment?沒有通過搜索SO或文檔找到任何東西。

謝謝

+0

我不知道這是否幫助你:[從DOM創建可重用的文檔片段](http://stackoverflow.com/questions/14048432/create-reusable-document-fragment-from-the-dom) –

+0

@ j.kherfan謝謝,但我沒有看到他們將任何東西轉換回DocumentFragment – user777

回答

0

我建議保留你感興趣的節點在一個數組中。 DocumentFragment更方便,而不像NodeList或HTMLCollection那樣討厭。

將「東西」轉換爲documentFragments的一個小工具。

function fragmentFlush(state){ 
    if(state.text){ 
     state.fragment.appendChild(document.createTextNode(state.text)); 
     state.text = ""; 
    } 
    return state.fragment; 
} 

function fragmentIterate(state, value){ 
    if(value instanceof Node){ 
     fragmentFlush(state).appendChild(value); 
    }else if(Array.isArray(value)){ 
     value.reduce(fragmentIterate, state); 
    }else if(value === Object(value)){ 
     fragmentIterate(state, Array.from(value)); 
    }else if(value != null){ 
     state.text += value; 
    } 
    return state; 
} 

function fragment(value){ 
    return fragmentFlush(fragmentIterate({ 
     text: "", 
     fragment: document.createDocumentFragment() 
    }, value)); 
} 

「東西」,因爲它穿越任何(非循環)arraylike結構找到你所經過的節點,並建立從一個(扁平化)的DocumentFragment。 (原始值轉換爲TextNodes,nullundefined被忽略)

var setA = [/*...*/]; 

var frag = fragment([ 
    "setA: ", setA, 
    condition? "some more text": null, //null values are ignred 
    "setB: ", someNode.children, 
    //that's why I made this traverse recursively 
    //so that I can "concat" lists like the following line 
    //without having to actually concat them 
    "setC: ", [setA, anotherSet, /* moreNodes */, andAnotherSet] 
]); 

node.appendChild(frag); 

同樣要注意,不循環引用處理!

關於這三個函數,我剛剛從我的一個庫中提取了這個函數。你可能想把它放到一個模塊中,只輸出fragment或將它包裝到一個IIFE中。