Обмен узлов между двумя деревьями
Здравствуйте!!!
Хочу разобраться как можно осуществить смену узлов 2х деревьев с n вложенностью(узел получаем по клику, по факту это будет драг энд дроп). Корневой узел перетаскивает всех дочерних, любой дочерний может стать корневым и дочерним для любого другого узла в своем дереве или соседнем. Учитывается позиция. 1. Какие нужно учесть условия чтобы это стало возможо? 2. Задачка конечно ппц, хочется както понять с чего начать) Допустим есть входящие данные такие:
const tree1 = [
{
id: 1,
title: 'node1',
children: [
{
id: 3,
title: 'sub node1' ,
},
{
id: 4,
title: 'sub node1' ,
children: [ { id: 5, title: 'sub sub node1'}]
}
] ,
},
{
id: 2,
title: 'node2',
children: [
{
id: 6,
title: 'sub node2' ,
},
{
id: 7, title: 'sub node2' ,
children: [ { id: 8, title: 'sub sub node2'}]
}
] ,
}
];
const tree2 = [
{
id: 9,
title: 'node1',
children: [
{
id: 10,
title: 'sub node1' ,
},
{
id: 11, title: 'sub node1' ,
children: []
}
] ,
},
{
id: 12,
title: 'node2',
children: [
{
id: 13,
title: 'sub node2' ,
},
{
id: 14,
title: 'sub node2' ,
children: [ { id: 15, title: 'sub sub node2'}]
}
] ,
}
];
const treeToTreeNodes = (tree1, tree2) => {
}
|
По моему у ваших деревьев не хватает полноценного корня.
Должно быть как то так
const tree1 = {
id: 0,
title: 'root',
children: [
{
id: 1,
title: 'node1',
children: [
{
id: 3,
title: 'sub node1' ,
},
{
id: 4,
title: 'sub node1' ,
children: [ { id: 5, title: 'sub sub node1'}]
}
] ,
},
{
id: 2,
title: 'node2',
children: [
{
id: 6,
title: 'sub node2' ,
},
{
id: 7, title: 'sub node2' ,
children: [ { id: 8, title: 'sub sub node2'}]
}
] ,
}
]
};
const treeToTreeNodes = (tree1, tree2) => {} И какая конкретно операция должна быть выполнена? Что вставить и куда? |
Допустим я беру и удаляю ноду из tree2:
{
id: 12,
title: 'node2',
children: [
{
id: 13,
title: 'sub node2' ,
},
{
id: 14,
title: 'sub node2' ,
children: [ { id: 15, title: 'sub sub node2'}]
}
] ,
}
и ее вставляю в tree1 между:
{
id: 6,
title: 'sub node2' ,
},
и
{
id: 7, title: 'sub node2' ,
children: [ { id: 8, title: 'sub sub node2'}]
}
и так далее все возможные комбинации. |
Если такие операции требуются часто, я бы сделал класс, хотя бы с минимально необходимыми функциями работы с деревом.
Ну как то так
class Node {
// Создает узел дерева.
// fields - объект с полями определяемыми пользователем
// childs - массив дочерних узлов (необязат)
constructor (fields, childs) {
this.parent = null;
this.childs = [];
for (const f in fields) {
this[f] = fields[f];
}
if (childs) {
for (const ch of childs) {
this.append(ch);
}
}
}
// Добавить узел nd, как последний дочерний к текущему
append (nd) {
nd.remove();
nd.parent = this;
this.childs.push(nd)
return this
}
// Найти в текущем и среди всех его потомков узел, удовлетворяющий условию,
// задаваемому функцией fcmp
find (fcmp) {
if (fcmp(this)) return this;
for (const ch of this.childs) {
const rf = ch.find (fcmp)
if (rf) return rf;
}
return null;
}
// Удалить узел
// nd.remove () удаляет узел nd из его родителя.
// par.remove (nd) удаляет из дочерних par узел nd
remove (nd) {
let par = this;
if (nd === undefined) {
par = this.parent;
nd = this;
}
if (!par || !nd) return
const ind = par.childs.indexOf(nd);
if (ind < 0) return;
par.childs.splice(ind, 1);
nd.parent = null;
return nd;
}
// Вставляет узел nd перед текущим, в его родительский узел, если он есть
before (nd) {
const par = this.parent;
if (!par) return;
nd.remove();
const ind = par.childs.indexOf(nd);
par.childs.splice(ind, 0, nd)
nd.parent = this;
return this;
}
toString () {
let s = '{'
for (const f in this) {
if (f == 'childs') continue;
if (f == 'parent') continue;
s += `${f}: ${this[f].toString()}, `
}
s+='childs: ['
for (const ch of this.childs) {
s+=ch.toString() + ','
}
s+=']}'
return s
}
}
const tree1 = new Node ({},
[
new Node ({id: 1, title: 'node1'},
[
new Node ({id: 3, title: 'sub node1'}),
new Node ({id: 4, title: 'sub node1'}, [new Node ({ id: 5, title: 'sub sub node1'})]),
]),
new Node ({id: 2, title: 'node2'},
[
new Node ({id: 6, title: 'sub node2'}),
new Node ({id: 7, title: 'sub node2'}, [new Node ({ id: 8, title: 'sub sub node2'})]),
])
]);
const tree2 = new Node ({},
[
new Node ({id: 9, title: 'node1'},
[
new Node ({id: 10, title: 'sub node1'}),
new Node ({id: 11, title: 'sub node1'}),
]),
new Node ({id: 12, title: 'node2'},
[
new Node ({id: 13, title: 'sub node2'}),
new Node ({id: 14, title: 'sub node2'}, [new Node ({ id: 15, title: 'sub sub node2'})]),
])
]);
console.log(tree1.toString());
console.log(tree2.toString());
// Допустим я беру и удаляю ноду из tree2:
// и ее вставляю в tree1 между:
const nd12 = tree2.find (nd => nd.id == 12)
const nd7 = tree1.find (nd => nd.id == 7)
nd7.before(nd12)
console.log(tree1.toString());
console.log(tree2.toString());
|
https://www.jstree.com/demo/
https://dbushell.github.io/Nestable/ и много других тут вопрос целесообразности своего велосипеда :cray: или изспользованя готовых либ :dance: как не крути если хочешь свое, то нужно смотреть, что есть хорошее у других пример с учебника и здесь на сайте где то в учебнике было примитивное дерево https://learn.javascript.ru/drag-and-drop-plus |
Цитата:
|
Цитата:
А оно надо? Зачем в простом случае тащить готовую либу, где 90% не требуется? Цитата:
|
Проблема сейчас в том что мне нужно подобие этого https://frontend-collective.github.i...-tree-dragging, но то что есть у них не работает, выдает ошибку.
|
Цитата:
в нынешнее время плевать на 10k на вебе можно в конце ТС ответил про react :lol: avesome react tree https://reactscript.com/best-tree-view/ с React не подскажу, у меня к нему особое мнение :) |
| Часовой пояс GMT +3, время: 23:23. |