DOM可以是DAG还是必须保留为树?

时间:2018-10-19 13:17:42

标签: javascript dom

令人困惑。我希望只是在谷歌上搜索这个问题 主题行会提供明确的答案,但由于甚至没有提示 我要问一个答案。

为了方便起见,以下代码使用D3,但问题是关于 DOM。随意使用(较小的IMHO)jQuery或(较小的) 如果愿意,可以使用准系统DOM操作代码进行回答。

许多DIV出现在左侧()。悬停在其中一个DIV上 在右侧()放大。

function magnify(i) {
    return function() {
        var right = d3.select("right");
        right.selectAll("*").remove();
        right.append("magunit")
             .html("<h2>" + i + "</h2>");
    }
}
for(i=0; i<256; i++) {
    var unit = d3.select("left").append("unit")
                 .on("mouseenter",magnify(i));
    unit.html("<h2>" + i + "</h2>");
}
html, body { width: 100%; height: 100%; margin: 0; }
mycontainer { width: 100%; height: 100%; display: flex; flex-flow: row; }
left { display: flex; flex-flow: row wrap; flex: 1; overflow-y: auto;}
right { display: flex; flex-flow: row; flex: 1; }
unit { flex: 1 1 auto; width: 80px; height: 60px; border: solid 1px black; }
<script src="https://d3js.org/d3.v5.min.js"></script>
    <mycontainer><left></left><right></right></mycontainer>

是否需要重新创建每个DIV?标准怎么说 从两片叶子指向现有的DIV,有效地使 DOM是有向无环图(DAG)而不是树?

can-the-dom-be-a-dag

澄清,回复Kaiido的评论

我在这里使用<unit>来代替任意复杂的代码,以使代码简短。重点是移动指针,而不是不断重新创建(任意复杂的)单元结构。因此,“仅更改<h2>中的文本”不会将其剪切,而是“切换到SVG并使用<use>”是正确的。

相关

2 个答案:

答案 0 :(得分:2)

我认为您是在问同一个元素是否可以是多个元素的子元素(例如,一个div是本身是同级的两个div的孩子),那么简单的答案是“否”。

考虑一下-如果您必须手工编写HTML,您将如何使用标记编写HTML? HTML基本上是一种书面标记语言,而DOM只是一种以编程方式表示HTML文档的方式,以便脚本可以对其进行操作。

我们对此有所限制,因为DOM中的任何内容都必须表示为有效的HTML,反之亦然。最终,浏览器将解析HTML文档,以便知道要显示的内容。该文档的结构严格来说(必须)是一棵树,因为在HTML(和XML)中,子元素是通过将它们放置在其父元素(即嵌套)中来创建的。无法使用这种格式来表达多亲关系。

如果我们今天再次设计Web,我们可能会做不同的事情,但这是我们将近30年前继承的遗产的一部分-那时JavaScript甚至都不是问题。

如果您想获得有关DOM和HTML文档之间关系的一般参考,我建议您先阅读https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/…。

另请参见https://w3.org/TR/2004/REC-DOM-Level-3-LS-20040407/load-save.html。这个W3C规范描述了DOM对象必须如何可从XML到XML进行序列化(当然,HTML是特定的一种)。如果它可序列化为XML,则它必须可表示为分层树,因为这就是XML的要求。

https://dom.spec.whatwg.org/#nodes是当前的生活水平,描述了DOM如何成为节点的分层树。

答案 1 :(得分:0)

不。我通过以下方式对其进行了测试:

var testdiv = document.createElement("div");
testdiv.innerHTML="Im testing";
document.body.insertBefore(testdiv,document.body.childNodes[0]);

所以我的testdiv贴在身体顶部。 现在,当将完全相同的节点附加到正文末尾时:

document.body.append(testdiv);

节点从顶部移除,并附加到底部。

但是,有一种解决方法。 javascript中的节点是对象,因此您可以向其添加其他参数。您可以使用它为每个节点元素设置一个ID,还可以存储数组中哪个元素位于哪个ID中。 作为一个基本示例:

var map=[];
var testdiv = document.createElement("div");
testdiv.innerHTML="Im testing";
testdiv.myID=1;
if (!map[1]) map[1]=[];
map[1].push(testdiv);

document.body.append(testdiv);

var testdiv2=testdiv.cloneNode(true);
testdiv2.myID=testdiv.myID;
document.body.append(testdiv2);
if (!map[1]) map[1]=[];
map[1].push(testdiv2);

现在,如果您查询地图的元素,它将返回2个ID为1的节点。此地图数组已连接到DOM中的那些节点。您可以通过查看节点的myID来获取DOM中节点的ID。