Обмен узлов между двумя деревьями
Здравствуйте!!!
Хочу разобраться как можно осуществить смену узлов 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, время: 16:39. |