在 DOM 中追加/删除的适当方法是什么<template>?



我正在为我正在编写的一个小游戏尝试将HTML添加到DOM中。我的设计要求首先打开主菜单系统,我想在其中弹出并删除元素集。

我的问题是,做这件事最有效的方法是什么?经过一些研究,我已经在主体中实现了元素,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));
}

更新:问题在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()后的Heap快照中,HTMLBodyELement中有两个HTMLBodyELement对象,一个具有正常数量的元素,另一个具有数千个元素。

重申一下:做我在这里要求的事情的最佳方法是什么?我目前的方法可以固定吗?怎么回事?

大多数时候,您最好显示隐藏元素,而不是添加删除。因此,只需将元素放在标记中,然后隐藏一个元素:

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

并显示:

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

或者CCD_ 2或CCD_。

或者使用一个类来隐藏它,然后删除该类来再次显示它:

CSS:

.hidden {
    display: none;
}

隐藏:

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

显示:

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

IE8和IE9(以及一些小众浏览器)没有classList,但如果你环顾四周,你可以找到一个填充程序。


旁注1:添加元素的代码会创建一个无效的结构,因为您没有从克隆的元素中删除id,而是附加了它。这意味着文档中的两个元素的id相同,这是无效的(OP使用<template>元素,并附加其内容,而不是它们。仔细看,Teej!)

旁注2:通过记住找到的元素,而不是两次调用document.querySelector,可以加快删除菜单项的代码。例如:

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

一项综合测试表明,这会使事情的速度翻倍(这可能看起来很明显,但像getElementsByTagName这样的旧方法不会是这样)。当然,只有当你看到实际的性能问题时,这才重要,但这就是你发布。。。

相关内容

最新更新