2014-04-15 41 views
0

我正在嘗試將HTML添加到我正在編寫的小遊戲的DOM中。我的設計要求首先提出一個主菜單系統,在這裏我想彈出並移除一組元素。在DOM上添加/刪除<template>的適當方法是什麼?

我的問題是,什麼是最有效的方法來做到這一點?經過一番研究,我在主體中實現了元素,其ID代表了它們包含的菜單部分。他們是這個樣子:

<template id="main"> 

    <div class="wrapper_inner"> 

     <main id="main_screen"> 

      <h1>Main menu</h1> 

      <nav class="vertical"> 

       <button type="button">Characters</button> 

       <button type="button">Planets</button> 

       <button type="button">Export...</button> 

       <button type="button">Settings</button> 

      </nav> 

     </main> 

    </div> 

</template> 

然後,我調用這些函數來更改菜單:

function clearMenu() 
{ 
    var content = document.querySelector('.wrapper_inner'); 
    if(content) document.body.removeChild(content); 
} 
function menuSystem(mode) 
{ 
    clearMenu(); 
    document.body.appendChild(document.querySelector('template#'+mode).content.cloneNode(true)); 
} 

UPDATE:問題是cloneNode()函數中。它似乎 創建一個不可訪問的文檔片段傳遞到身體。如果 有人可以找到解決方案,我會更新最佳答案。


但是......這是在擴展測試造成相當的問題。我敢肯定,每次會議只會更改菜單幾次,但我希望保持最高效率。這裏的問題顯示出來:

function test() 
{ 
    console.log("start test..."); 
    var start = new Date(); 
    for(var i=0; i<10000; i++) 
    { 
     menuSystem("main"); 
    } 
    clearMenu(); 
    console.log("test completed in " + Math.round(((new Date())-start)/1000) + " secs"); 
} 

這首次周圍5-7秒,16秒第二時間輸出。在Chrome開發工具中,雖然我很努力地理解輸出,但是我可以看到,對於每個獨特的「模式」,我切換到它會在內存中添加一個或兩個文檔片段,但這並不會被刪除......另外,在運行後的堆快照test()中,HTMLBodyELement在其中有兩個HTMLBodyElement對象,一個具有正常數量的元素,另一個具有數千個元素。

重申:什麼是最好的方法來做我所需要的?我目前的方法可以修復嗎?無論如何,這筆交易是什麼?

+3

使用文檔片段,不要在每次迭代時直接附加到DOM:http:// ejohn。 org/blog/dom-documentfragments/- 你也可能想要緩存那個querySelector調用 – CodingIntrigue

+1

據我所知,是documentfragments,他們不是? –

+0

不,它們仍然只是呈現不同的DOM元素。另外,您正在創建一個新的DOM元素,它不是'modalSystem'內的模板,並將其附加到DOM,因此您仍然不使用片段。 – CodingIntrigue

回答

3

大多數時候,你就要去更能顯出隱藏元素,而不是加入刪除他們。所以只是把元素您的標記,然後隱藏元素:

document.querySelector("some selector").style.display = "none"; 

,並顯示出它:

document.querySelector("some selector").style.display = "block"; 

...或"inline""inline-block"適當。

或者使用一個類來隱藏它,並刪除類再次顯示:

CSS:

.hidden { 
    display: none; 
} 

要隱藏:

document.querySelector("some selector").classList.add("hidden"); 

要顯示:

document.querySelector("some selector").classList.remove("hidden"); 

IE8和IE9(和一對夫婦利基瀏覽器)don't have classList,但如果你環顧四周,你可以找到一個墊片/ polyfill。


附註1:您的添加元素的代碼創建一個無效的結構,因爲你沒有從克隆的元素id,但你追加它。這意味着最終在文檔中有兩個元素與id相同,這是無效的。(op爲使用<template>元素和附加其內容,不是他們更仔細,Teej!)

附註2:您的移除菜單碼能夠通過記住元素有待加快你發現而不是打電話document.querySelector兩次。例如: -

function clearMenu() 
{ 
    var wrapperInner = document.querySelector('.wrapper_inner'); 
    if(wrapperInner) { 
     document.body.removeChild(wrapperInner); 
    } 
} 

一個synthetic test表明,雙打事物的速度(這似乎是顯而易見的,但不會與舊的方法,例如getElementsByTagName的情況下)。當然,這隻在看到實際性能問題時才重要,但因爲這就是爲什麼你要發佈......

+0

當然。這當然意味着任何事件處理程序都需要考慮元素可以隱藏起來。 – CodingIntrigue

+0

@Rraham:的確如此。 –

+0

因此,如果我的HTML中有幾個GUI層必須被預加載然後在與遊戲交互之前隱藏,那麼它不會被認爲是不好的形式?例如,目前我有三個可能的圖層(帶有子圖層?),例如:主菜單圖層 - >登錄,開始屏幕,字符屏幕,設置屏幕,暫停屏幕||遊戲gui層與字符健康等||遊戲菜單層 - >庫存,容器庫存,商店等 –

相關問題