Javascript 如何使用具有父子关系的JSON数据创建带有复选框的树?
我有JSON数据,JSON数据有父子关系。我想从中创建树结构。我找到了很多插件和库,但我找不到我的需求。我使用PHP脚本获取这个JSON数据 这是我想要创建的具有树结构的图像。我被卡住了。我知道JSON并不像图中显示的那个样,但我只想告诉你们树应该是什么样子。如何在图中创建树。我只想用javascript代码来处理和创建这种类型的树结构。工作的例子是必须和非常赞赏 您可以随意使用JSON格式,树应该是可折叠的。还可以为它提供所需的JSON格式 我的JSON数据如下:Javascript 如何使用具有父子关系的JSON数据创建带有复选框的树?,javascript,jquery,html,json,tree,Javascript,Jquery,Html,Json,Tree,我有JSON数据,JSON数据有父子关系。我想从中创建树结构。我找到了很多插件和库,但我找不到我的需求。我使用PHP脚本获取这个JSON数据 这是我想要创建的具有树结构的图像。我被卡住了。我知道JSON并不像图中显示的那个样,但我只想告诉你们树应该是什么样子。如何在图中创建树。我只想用javascript代码来处理和创建这种类型的树结构。工作的例子是必须和非常赞赏 您可以随意使用JSON格式,树应该是可折叠的。还可以为它提供所需的JSON格式 我的JSON数据如下: { "
{
"2":
{
"5": "Wrist Watch"
},
"5":
{
"9": "Men's"
},
"18":
{
"3": "Clothing"
},
"28":
{
"1": "Perfumes"
},
"29":
{
"7": "Laptop",
"10": "Tablets"
},
"30":
{
"8": "Mobile"
},
"31":
{
"2": "Books"
},
"33":
{
"6": "Electronics"
},
"34":
{
"4": "Home & Kitchen\n"
}
}
编程的问题是:现有的库和工具很少能完全满足您的需要。始终由您将输入数据转换为他们期望的格式,然后将输出数据转换为您需要的格式。有时,这种转换比编写自己的代码而不是库函数需要更多的努力——这似乎是其中之一 正如@philosophocat已经指出的,在HTML标记中呈现这样一个树的最好方法是嵌套列表。您只需递归地遍历JSON数据并创建相应的元素:
函数createList(数据)
{
var结果=document.createElement(“ul”);
for(var输入数据)
{
如果(!data.hasOwnProperty(key)| | key==“_title”)
继续;
var值=数据[键];
var item=createItem(key,typeof value==“string”?value:value.\u title);
如果(值的类型==“对象”)
item.appendChild(createList(value));
结果:儿童(项目);
}
返回结果;
}
函数createItem(值、标题)
{
var结果=document.createElement(“li”);
var checkbox=document.createElement(“输入”);
setAttribute(“类型”、“复选框”);
复选框.setAttribute(“名称”、“选择”);
复选框.setAttribute(“值”,值);
结果.追加子项(复选框);
result.appendChild(document.createTextNode(title));
返回结果;
}
document.body.appendChild(createList(jsonData));
请注意,此处项目的显示顺序为“随机”,因为对象键通常是无序的。您可以更改上面的代码以某种方式对键进行排序,也可以更改数据以使用数组并定义顺序。我还为数据添加了一个“\u title”
属性,以确保已标记类别-您的数据中没有任何类别的标签
现在,您需要以使列表看起来像一棵树的方式设置列表的样式。显而易见的解决方案是使用网格线图像替换通常的项目符号。但是,这对嵌套列表不起作用-在嵌套列表中,您需要显示多个图像、高层列表中的垂直线以及实际属于当前列表项的图像
这可以通过为列表项使用背景图像来解决,这些背景图像也将显示在子列表旁边。以下是我得到的示例样式:
ul
{
填充:0;
列表样式类型:无;
字体大小:14px;
}
锂
{
背景图片:url(数据:image/png;base64,ivborw0kggoaaansuheugaa0aaabkcayaaabdelruaaap0leqvr42u3pqoaiageqp3/o6t7JAhdolkQD4sMZuwZazKKlGXniHRDOu6HfyKRSCQSiUQikUgkEolEIv0rTc/fNmQ78+lpaaaelftksuqmcc);
背景重复:无重复;
左侧填充:13px;
}
李:最后一个孩子
{
背景图片:url(数据:image/png;base64,ivborw0kggoaaaansuheugaa0aaaajcayaadpeqzqaaahuleqvr42mnkwat/gzirak/ak0mkplgbqgethoacfgjcvdbeqaaaaaaasuvork5cyii=);
}
li>ul
{
左边距:5px;
}
请注意,如果子列表太高,这仍然会变得难看-我使用的背景图像的高度仅为100px。当然,这可以通过使用更大的背景图像来解决。一个更干净的替代方案是使用Firefox,但目前只支持Firefox
编辑:详细介绍如何设置嵌套列表(如树)的样式。虽然该方法类似,但它通过为垂直线使用单独的图像(可以垂直重复)来避免我上面提到的图像大小问题。另一方面,这种方法似乎只适用于实线,如果应用于虚线,则可能会产生瑕疵。如果您想自己滚动,“树”中的关键字是递归。它需要支持任何深度的数据,代码和数据都应该支持递归 这意味着您的JSON数据应该是一个递归结构,其中每个节点看起来都是相同的(如下所示): 注意:我已经更改了示例数据以包含更多深度,因为2个级别从未出现递归问题 e、 g: 递归函数如下所示:
{
id: 1, // data id
title: "title", // display title
children: [ // list of children, each with this same structure
// list of child nodes
]
}
function addItem(parentUL, branch) {
for (var key in branch.children) {
var item = branch.children[key];
$item = $('<li>', {
id: "item" + item.id
});
$item.append($('<input>', {
type: "checkbox",
name: "item" + item.id
}));
$item.append($('<label>', {
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>').appendTo($item);
addItem($ul, item);
}
}
}
最终结果如下所示:
{
id: 1, // data id
title: "title", // display title
children: [ // list of children, each with this same structure
// list of child nodes
]
}
function addItem(parentUL, branch) {
for (var key in branch.children) {
var item = branch.children[key];
$item = $('<li>', {
id: "item" + item.id
});
$item.append($('<input>', {
type: "checkbox",
name: "item" + item.id
}));
$item.append($('<label>', {
for: "item" + item.id,
text: item.title
}));
parentUL.append($item);
if (item.children) {
var $ul = $('<ul>').appendTo($item);
addItem($ul, item);
}
}
}
如果要根据选中状态切换可见性,请使用以下选项:
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
如果还希望标签切换复选框,请使用以下选项:
$(':checkbox').change(function () {
$(this).closest('li').children('ul').slideToggle();
});
$('label').click(function(){
$(this).closest('li').find(':checkbox').trigger('click');
});
注:我只提供了最基本的造型,因为这通常是“品味”。链接中的示例显示在另一个答案中
--更新:
修正:项目31和32的ID可能错误
用于更好地选择和取消选择的函数(对于级联到子节点的父节点):
--如图所示()更新fiddle,它将工作得更好,还允许您单击文本展开,而无需同时选择-我知道我发现这更有用。它将帮助(这是个人偏好)您查看哪些值和选项可用,而无需选择第一个。使用。这个库提供了我在使用树和javascript时需要的每个函数
您只需根据给定的格式()更改json响应:
设置javascript并包含所有必需的fi
{
"title": "Sports & Outdoors",
"isFolder": true,
"key": "0",
"children": [
{
"title": "Fitness Accessories",
"key": "1",
"isFolder": true,
"children": [
{
"title": "Fitness Accessories",
"key": "2",
"isFolder": true,
"children": [
{
"title": "Pedometer & Watches",
"key": "3"
}
]
}
]
}
]
}
$("#buildTree").dynatree({
onActivate: function (node) {
// A DynaTreeNode object is passed to the activation handler
// Note: we also get this event, if persistence is on, and the page is reloaded.
leftActiveNodeKey = node.data.key;
},
persist: false,
checkbox: true,
selectMode: 3,
children: $.parseJSON(response.d)
});
$(this).prop('checked', false);
$(function () {
addItem($('#root'), data);
$(':checkbox').click(function () {
var matchingId = $(this).attr('id');
if ($(this).attr('checked'))
{
$('input[id*=' + matchingId +']').each(function() {
$(this).removeAttr('checked');
$(this).prop('checked', false);
$(this).prop('checked', $(this).attr('checked'));
return;
});
}
else {
$('input[id*=' + matchingId +']').each(function() {
$(this).attr('checked', 'checked');
$(this).prop('checked', $(this).attr('checked'));
});
}
});
$('label').click(function(){
$(this).closest('li').children('ul').slideToggle();
});
});