我有一个JSON对象,用于使用列表构建树形视图。 JSON对象具有以下结构;
const data = [
{ "name": "Node 1", "children":
[
{ "name": "Node 1.1", "children":
[
{ "name": "Node 1.1.1", "children": [], "leaf": true },
{ "name": "Node 1.1.2", "children": [], "leaf": true }
]
},
{ "name": "Node 1.2", "children":
[ { "name": "Node 1.2.1", "children": [], "leaf": true } ]
}
]
},
{ "name": "Node 2", "children":
[
{ "name": "Node 2.1", "children": [] },
{ "name": "Node 2.2", "children":
[ { "name": "Node 2.2.1", "children": [], "leaf": true } ]
}
]
},
{ "name": "Node 3", "children": [] }
];
然后在createTree
函数中使用该对象;
createTree(nodes, container)
{
const list = document.createElement('ul');
nodes.forEach((node) => {
const listItem = document.createElement('li');
listItem.textContent = node.name;
list.appendChild(listItem);
if (node.children) {
const childList = document.createElement('li');
this.createTree(node.children, childList);
list.appendChild(childList);
}
});
container.appendChild(list);
}
nodes
最初是data
对象,container
是放置树的元素。此函数将构建以下树视图;
<ul>
<li>Node 1</li>
<li>
<ul>
<li>Node 1.1</li>
<li>
<ul>
<li>Node 1.1.1</li>
<li>
<ul></ul>
</li>
<li>Node 1.1.2</li>
<li>
<ul></ul>
</li>
</ul>
</li>
<li>Node 1.2</li>
<li>
<ul>
<li>Node 1.2.1</li>
<li>
<ul></ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Node 2</li>
<li>
<ul>
<li>Node 2.1</li>
<li>
<ul></ul>
</li>
<li>Node 2.2</li>
<li>
<ul>
<li>Node 2.2.1</li>
<li>
<ul></ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Node 3</li>
<li>
<ul></ul>
</li>
</ul>
这几乎是我想要的方式,有很多不必要的li
和ul
标签,但是因为我使用的是list-style-type: none
,所以没有必要,不必要的元素是折叠且未显示。
我还添加了一个输入字段,用于过滤树并仅显示相关的叶子(因此JSON对象中的leaf
值)。它应该仅显示相关的叶子,还应显示其父母。我已经通过以下过滤器功能部分完成了此操作;
$('#input').on('keyup', () => {
const value = $('#input').val().toLowerCase().trim();
const nodes = oldData.filter(function f(node) {
if (node.name.toLowerCase().includes(value)) return true;
if (node.children) {
return (node.children = node.children.filter(f)).length;
}
});
// Simply removes all children from the root element so there's only one tree, instead of the new tree being stacked on top of the new one
this.removeTree();
// Rebuild the new tree
this.createTree(nodes, document.getElementById('root-element'));
});
从某种意义上讲,它仅显示包括其父节点的相关叶子,但是如果您清空输入字段,则仅使搜索词之后可见的元素可见。我知道为什么会这样(filter
函数会删除所有不匹配项),但我不知道如何防止这种情况的发生。我尝试将data
的初始状态存储在keyup
事件侦听器外部的变量中,并在输入字段为空时将nodes
设置为该变量,但这并没有似乎有帮助。
我也尝试遍历实际的HTML树,但是我什至无法正确访问节点1、2和3的孩子,所以我也很茫然。
换句话说,最好的方法是在过滤树的叶子的同时显示其父级,并在过滤器为空后恢复原始状态?
使用jQuery.grep()
;
const nodes = $.grep(data, function f(node) {
if (node.name.toLowerCase().includes(value)) return true;
});
答案 0 :(得分:1)
据我了解,您有2个问题。
let oldData = data;
时,您将获得指向初始“数据”对象而不是另一个对象的链接。我通过JSON使用了很多复制对象的方法。$(document).ready(() => {
createTree(data, $('#container'));
$('#asdf').on('keyup', () => {
let dataCopy = JSON.parse(JSON.stringify(data));
const value = $('#asdf').val().toLowerCase().trim();
let nodes = {};
if (!value) { nodes = data; } else {
nodes = filterData(dataCopy, value);
}
// Simply removes all children from the root element so there's only one tree, instead of the new tree being stacked on top of the new one
this.removeTree();
// Rebuild the new tree
this.createTree(nodes, $('#container'));
});
});
function filterData(data, name) {
return data.filter(function(o) {
if (o.children) o.children = filterData(o.children, name);
return o.name.toLowerCase().includes(name) || o.children.length;
});
}