我正在尝试以HTML ul
列表方式显示JavaScript对象。
该对象表示二叉树,具有以下格式:
{
"val":2,
"l":{
"val":1,
"l":{},
"r":{}
},
"r":{
"val":4,
"l":{},
"r":{
"val":5,
"l":{},
"r":{}
}
}
}
我需要完成的结果是:
<ul>
<li>
<a href="#">2</a>
<ul>
<li>
<a href="#">1</a>
</li>
<li>
<a href="#">4</a>
<ul>
<li>
<a href="#">5</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
我在这里编写此代码是为了获取结果的相应字符串,但它不会生成正确的结果。
function buildList(data){
var html = '';
if(data.val){
if(data.l){
html += '<ul>';
html += buildList(data.l);
}
html += '<li>';
html += '<a href="#">' + data.val + '</a>'
html += '</li>';
if(data.r){
html += buildList(data.r);
html += '</ul>';
}
}
return html;
}
任何猜测或线索都会受到赞赏。
答案 0 :(得分:2)
让生活更轻松
这种情况下,一点点的数据抽象是一种低调的方式。如果您尝试在单个函数中处理数据中的所有差异,您将面临单分支if
和其他副作用代码的大意大利面。
使用下面的数据抽象,我将复杂的逻辑和条件简化为单个if/else
语句。我将逐步逐步完成代码,然后我将它们放在最后的可运行演示中
一厢情愿
我不想考虑(例如)val是{}
还是l
或r
具有有效价值 - 这对我来说毫无意义。我想写的是这样的:
const makeTree = ({val, l, r}) => {
if (val === undefined)
return []
else
return [Node('ul', Node('li', Link('#', val)), ...makeTree(l), ...makeTree(r))]
}
这假设我们有两个构造函数Node
和Link
。但在我们深入研究之前,我们看到makeTree
无论如何都返回一个数组。因此,我们必须提出一个很好的面向用户的功能,以某种方式为我们构建HTML。这将是makeMenu
- 所有这一切都需要将根节点从数组中取出并在其上调用.toElem()
const makeMenu = data =>
makeTree(data)[0].toElem()
这也有助于我们了解我们需要在.toElem
和Node
两种节点类型上使用Link
。看,使用一厢情愿的想法很好地构建你的程序,因为你想要的每一步都告诉你你必须构建的下一件事。
Node
和Link
构造函数
现在让我们点击Node
和Link
。他们非常直截了当。 Node
只是特定type
的通用HTML元素,可以将子元素应用于它;请注意,每个孩子也应该有.toElem
方法。 Link
只需要href
和一些text
,然后根据相应的属性构建元素。
const Node = (type, ...children) => ({
toElem: () => {
const elem = document.createElement(type)
children.forEach(child => elem.appendChild(child.toElem()))
return elem
}
})
const Link = (href, text) => ({
toElem: () => {
const elem = document.createElement('a')
elem.setAttribute('href', href)
elem.textContent = text
return elem
}
})
全部放在一起
const Node = (type, ...children) => ({
toElem: () => {
const elem = document.createElement(type)
children.forEach(child => elem.appendChild(child.toElem()))
return elem
}
})
const Link = (href, text) => ({
toElem: () => {
const elem = document.createElement('a')
elem.setAttribute('href', href)
elem.textContent = text
return elem
}
})
const makeTree = ({val, l, r}) => {
if (val === undefined)
return []
else
return [Node('ul', Node('li', Link('#', val)), ...makeTree(l), ...makeTree(r))]
}
const makeMenu = data =>
makeTree(data)[0].toElem()
const data = { "val": 2, "l": { "val": 1, "l": {}, "r": {} }, "r": { "val": 4, "l": {}, "r": { "val": 5, "l": {}, "r": {} } } }
document.body.appendChild(makeMenu(data))
&#13;
答案 1 :(得分:1)
您可以通过使用所需对象构建DOM节点来使用动态递归方法。
function buildDOM(tree) {
function buildLI(node) {
var li = document.createElement('li'),
a = document.createElement('a');
a.href = '#';
a.appendChild(document.createTextNode(node.val));
li.appendChild(a);
if (('l' in node) && ('val' in node.l) || ('r' in node) && ('val' in node.r)) {
li.appendChild(buildDOM(node));
}
return li;
}
var ul = document.createElement('ul');
if (('l' in tree) && ('val' in tree.l)) {
ul.appendChild(buildLI(tree.l));
}
if (('r' in tree) && ('val' in tree.r)) {
ul.appendChild(buildLI(tree.r));
}
return ul;
}
var data = { val: 2, l: { val: 1, l: {}, r: {} }, r: { val: 4, l: {}, r: { val: 5, l: {}, r: {} } } };
document.body.appendChild(buildDOM({ r: data }));
答案 2 :(得分:0)
你只需稍微重新排列代码即可。这是一个有效的解决方案:
function buildList(data){
var html = '';
if(data.val){
html += '<ul><li>';
html += '<a href="#">' + data.val + '</a>'
html += '</li>';
if(data.l){
html += buildList(data.l);
}
if(data.r){
html += buildList(data.r);
html += '</ul>';
}
}
return html;
}
var resultDiv = document.getElementById('resultDiv');
var testData =
{
"val":2,
"l":{
"val":1,
"l":{},
"r":{}
},
"r":{
"val":4,
"l":{},
"r":{
"val":5,
"l":{},
"r":{}
}
}
};
resultDiv.innerHTML = buildList(testData);
&#13;
<p>Actual Result:</p>
<div id="resultDiv">...</div>
<hr>
<p>Desired Result:</p>
<ul>
<li>
<a href="#">2</a>
<ul>
<li>
<a href="#">1</a>
</li>
<li>
<a href="#">4</a>
<ul>
<li>
<a href="#">5</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
&#13;
答案 3 :(得分:0)
var dom = buildList(yourObject);
final(dom);
function buildList(data){
if(data.val){
var currentTag = document.createElement('li');
var atag = document.createElement('a');
atag.setAttribute("href", "#");
atag.innerText = data.val;
currentTag.appendChild(atag);
if(JSON.stringify(data.l) != "{}" || JSON.stringify(data.r) != "{}"){
var ulTag = document.createElement('ul');
if(JSON.stringify(data.l) != "{}"){
ulTag.appendChild( buildList(data.l));
}
if(JSON.stringify(data.r) != "{}"){
ulTag.appendChild( buildList(data.r));
}
currentTag.appendChild(ulTag);
}
}
return currentTag;
}
function final(body) {
body = document.createElement('ul').appendChild(body);
}