ДеревоЗначений — один из самых коварных объектов. Оно идеально для визуализации иерархии, но при неправильном подходе превращает интерфейс в «тыкву». Главная проблема — сериализация: при каждом серверном вызове дерево гоняется целиком. Если в нем 100 000 строк, интерфейс «умрет». Разберем, как заставить его летать.
- Ленивая загрузка (Lazy Loading) — Технически верно
Чтобы дерево открывалось мгновенно, подгружайте данные только при развертывании узла.
Шаг 1: Создаем маркер-пустышку (Сервер)
Если у узла есть дети, нужно «обмануть» платформу, чтобы она отрисовала «плюсик». Для этого добавляем одну пустую строку.
bsl
// На сервере при заполнении уровня (инициализация корня)
НоваяСтрока = КоллекцияВерхнегоУровня.Добавить();
НоваяСтрока.Наименование = "Группа товаров";
Если Выборка.ЭтоГруппа Тогда
// ПРАВИЛЬНО: Добавляем пустую подчиненную строку-маркер.
// Платформа увидит Количество() > 0 и нарисует "+" у узла.
НоваяСтрока.ПолучитьЭлементы().Добавить();
КонецЕсли;
Шаг 2: Обработка события (Клиент)
Используем штатное событие таблицы ПередРазворачиванием(Элемент, Строка, Отказ). Параметр Строка здесь — это идентификатор (Число).
bsl
&НаКлиенте
Процедура ДеревоПередРазворачиванием(Элемент, Строка, Отказ)
Узел = ДеревоДанных.НайтиПоИдентификатору(Строка);
Дочерние = Узел.ПолучитьЭлементы();
// ПРОВЕРКА: Если там только наша "пустышка" (одна строка без данных)
Если Дочерние.Количество() = 1 И Дочерние.Ссылка.Пустая() Тогда
ПодгрузитьДанныеНаСервере(Строка);
КонецЕсли;
КонецПроцедуры
Шаг 3: Дозагрузка данных (Сервер)
bsl
&НаСервере
Процедура ПодгрузитьДанныеНаСервере(ИдентификаторСтроки)
РодительскийУзел = ДеревоДанных.НайтиПоИдентификатору(ИдентификаторСтроки);
Коллекция = РодительскийУзел.ПолучитьЭлементы();
Коллекция.Очистить(); // Удаляем маркер-пустышку
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Наименование, ЭтоГруппа ИЗ Справочник.Номенклатура ГДЕ Родитель = &Родитель");
Запрос.УстановитьПараметр("Родитель", РодительскийУзел.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = Коллекция.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
Если Выборка.ЭтоГруппа Тогда // Снова ставим маркер для следующего уровня
НоваяСтрока.ПолучитьЭлементы().Добавить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
- Рекурсия vs Итеративный обход (Стек)
Рекурсия — это красиво, но медленно и опасно (Stack Overflow). 1С тратит ресурсы на каждый вызов процедуры и управление стеком.
КАК НЕ НАДО, Если Деревозначений имеет большой объем(Рекурсия):
bsl
Процедура Обход(Строки)
Для Каждого Стр Из Строки Цикл
// Обработка...
Если Стр.Строки.Количество() > 0 Тогда // Лишний вызов метода в каждой итерации
Обход(Стр.Строки); // Рекурсивный вызов - ТОРМОЗИТ!
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Оптимальное (Итеративный обход через массив-стек):
Работает в 1.5–2 раза быстрее и никогда не упадет.
bsl
Процедура ОбходИтеративный(КорневыеСтроки)
Стек = Новый Массив;
Для Каждого Стр Из КорневыеСтроки Цикл Стек.Добавить(Стр); КонецЦикла;
Пока Стек.Количество() > 0 Цикл
ТекущаяСтрока = Стек[Стек.Количество() - 1];
Стек.Удалить(Стек.Количество() - 1);
// --- Полезная работа здесь ---
Подчиненные = ТекущаяСтрока.Строки;
Для Каждого Подч Из Подчиненные Цикл
Стек.Добавить(Подч);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
- Поиск: Забудьте про циклы
Метод НайтиСтроки(СтруктураОтбора, Истина) — это «черная магия» платформы на C++.
Почему это оптимально: платформа обходит дерево напрямую в памяти, не создавая объекты «Строка» в интерпретаторе 1С.
Когда НЕ использовать: если нужно искать 10 000 раз в цикле. В этом случае выгрузите дерево в ТаблицуЗначений, проиндексируйте её и ищите через ТЗ.Найти().
- Оптимизация через СКД
Если дерево — это сложный отчет с итогами, не собирайте его запросами в цикле:
Настройте СКД с иерархией группировок.
Используйте ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений.
СКД соберет дерево на уровне SQL и внутренних алгоритмов ядра, что в разы быстрее ручного заполнения.
Итоговый чек-лист производительности
| Операция | Ошибка (Тормоза) | Решение (Скорость) |
| Загрузка | Все дерево сразу | Ленивая загрузка + «Пустышка» |
| Обход | Рекурсия | Цикл Пока + Массив (Стек) |
| Поиск | Цикл Для Каждого | НайтиСтроки(…, Истина) |
| Оформление | Сложные формулы И/ИЛИ | Колонка-индекс цвета |
ДеревоЗначений — это визуальный объект, а не вычислительный. Считайте в таблицах или СКД, а пользователю отдавайте данные порциями через «Ленивую загрузку».
Словарь
| Tree (дерево) | Иерархическая структура данных в форме списка значений 1С — ноды с ветвями и листьями |
| ValueTree | Дерево значений — объект платформы 1С для хранения иерархических данных |
| Node | Узел дерева — элемент иерархии в дереве значений |
| Performance | Производительность — скорость обработки данных в дереве при большом количестве строк |
Все комментарии
Чтобы оставить комментарий, необходимо войти или зарегистрироваться.
Пока нет комментариев. Будьте первым!