#javascript #jquery
#javascript #jquery
Вопрос:
Привет, я хочу получить вложенную древовидную структуру, основанную на вложенности
Что-то вроде этого
<ul>
<li>Root
<ul>
<li>First level item 1</li>
<li>
First level item 2
<ul>
<li>second level item1</li>
</ul>
</li>
</ul>
</li>
Вопрос: моя функция неправильно возвращает разметку древовидной структуры.
Примечание: я не хочу добавлять еще 1 цикл
Вот что я пробовал:
var getTreeStrucureTemplate = dataset => {
var hashTable = Object.create(null), ul = '',li = '';
dataset.forEach(function(aData){
hashTable[aData.id] = {...aData, childNodes: []};
ul = '<ul>';
});
var dataTree = [];
dataset.forEach(aData => {
if(aData.parentId) { hashTable[aData.parentId].childNodes.push(hashTable[aData.id]); ul = '<li>' aData.name '</li>';}
else { dataTree.push(hashTable[aData.id]); ul = '</ul><ul>' }
// console.log(ul);
});
//console.log(dataTree);
var treeStructure = ul;
return treeStructure;
};
var list = [
{
"parentId": 0,
"id": 1,
"name": "Root"
},
{
"parentId": 1,
"id": 2,
"name": "First Level item 1"
},
{
"parentId": 1,
"id": 3,
"name": "First Level item 2"
},
{
"parentId": 3,
"id": 4,
"name": "second Level item 1"
}
];
console.log(getTreeStrucureTemplate(list))
Комментарии:
1. @ValiD tree будет любой вложенной структурой. итак, я делаю это так
2. Разрешено ли изменять структуру данных? Вероятно, у меня был бы массив дочерних объектов в качестве свойства для каждого объекта элемента списка, что значительно упрощает рекурсивную генерацию.
3. @DBS, почему бы и нет, но с минимальными циклами
Ответ №1:
Вот как я бы поступил по этому поводу:
- Используйте вложенную структуру данных с каждым объектом, содержащим его дочерние элементы
- Используйте набор рекурсивных функций, которые вызывают друг друга, чтобы автоматически обрабатывать любое количество слоев
(Он выполняется столько раз, сколько необходимо, но считаете ли вы рекурсивные функции циклами, зависит от вас)
var getListItems = dataset => {
// Create a string containing the items for this list
return dataset.map(item => {
// Build a nested UL string by calling getTreeStrucureTemplate on this objects children
var nested = getTreeStrucureTemplate(item.children || [])
// Build the current item and add any nested lists
return `<li>${ item.name }</li>${ nested }`
}).join('') // Join the items into a single string
}
var getTreeStrucureTemplate = dataset => {
// Only wrap the list in UL if it has contents
if (dataset.length) {
return `<ul>${ getListItems(dataset) }</ul>`
} else {
return ''
}
};
var list = [{
"name": "A",
"children": [{
"name": "B",
"children": [{
"name": "C"
},
{
"name": "D"
}]
}]
},
{
"name": "E",
"children": [{
"name": "F"
}]
}
]
var test = getTreeStrucureTemplate(list)
document.getElementById('test').innerHTML = test
console.log(test)
<div id="test"></div>
Комментарии:
1. решение кажется хорошим, но я хочу применить его к плоскому списку на основе
id,parentId
Ответ №2:
Я пытался работать со структурой, которую вы указали здесь в своем вопросе. Я не совсем понимаю, где вы не хотите использовать другой цикл, но вот мое предложение по решению вашей проблемы.
var getTreeStrucureTemplate = dataset => {
var hashTable = {}, ul = '',li = '';
var dataTree = [];
dataset.forEach(item => {
if (item.parentId) {
if (hashTable[item.parentId]) {
hashTable[item.parentId].childNodes.push(item);
} else {
hashTable[item.parentId] = {id: item.patentId, childNodes: [item]};
}
} else {
hashTable[item.id] = {...item, childNodes: []};
}
});
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
console.log(hashTable)
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
Object.values(hashTable).forEach(node => {
ul = '<ul>' node.name;
node.childNodes.forEach(subNode => {
ul = '<li>' subNode.name '</li>';
});
ul = '</ul>';
})
return ul;
};
var list = [
{
"parentId": 0,
"id": 1,
"name": "First Level"
},
{
"parentId": 1,
"id": 2,
"name": "First Level item 1"
},
{
"parentId": 0,
"id": 3,
"name": "First Level 2"
},
{
"parentId": 3,
"id": 4,
"name": "First Level 2 item 1"
}
];
console.log(getTreeStrucureTemplate(list))
Я печатаю массив после его переформатирования в желаемый способ.
Я думаю, вы можете улучшить этот код с точки зрения производительности, если сочтете нужным, но то, как он написан здесь, должно быть довольно ясно, чего мы пытаемся достичь.
Я надеюсь, что это поможет.
обновленная версия для поддержки столько вложенных уровней, сколько вы хотели бы:
var getTreeStrucureTemplate = dataset => {
var hashTable = {}, ul = '',li = '';
var dataTree = [];
dataset.forEach(item => {
if (item.parentId) {
if (hashTable[item.parentId]) {
hashTable[item.parentId].childNodes.push(item);
} else {
hashTable[item.parentId] = {id: item.patentId, childNodes: [item]};
}
} else {
hashTable[item.id] = {...item, childNodes: []};
}
});
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
console.log(hashTable)
console.log('-=-=-=-=-=-=-=-=-=-=-=-=-=-');
Object.values(hashTable).forEach(node => {
ul = createSubTree(node);
})
return ul;
};
var createSubTree = tree => {
var str = '';
str = '<ul>' tree.name;
tree.childNodes.forEach(subNode => {
str = '<li>' subNode.name '</li>';
if (subNode.childNodes amp;amp; subNode.childNodes.length) {
str = createSubTree(subNode.childNodes);
}
});
str = '</ul>';
return str;
}
var list = [
{
"parentId": 0,
"id": 1,
"name": "First Level"
},
{
"parentId": 1,
"id": 2,
"name": "First Level item 1"
},
{
"parentId": 0,
"id": 3,
"name": "First Level 2"
},
{
"parentId": 3,
"id": 4,
"name": "First Level 2 item 1"
}
];
console.log(getTreeStrucureTemplate(list))
это то, что вы ищете?
Комментарии:
1. он формирует отдельный ul для каждого вложенного дерева. по крайней мере, он должен работать с 2-3 уровнями вложенности
2. я отредактировал свой древовидный список, но ваш обновленный код все еще не работает
3. Можете ли вы поделиться набором данных, с которым вы работаете, чтобы увидеть, где он терпит неудачу?