При разработке и сопровождении конфигураций на платформе 1С:Предприятие 8.3 разработчики часто сталкиваются с ситуацией, когда в режиме тонкого клиента управляемая форма открывается и функционирует идеально, а в веб-клиенте интерфейс отображается с ошибками, зависает или выглядит так, будто серверные обработчики вовсе не отработали. Разберем механизм возникновения этой проблемы, выясним, почему отладка может вводить в заблуждение, и рассмотрим надежные способы устранения неполадки.
Первое впечатление при возникновении сбоя в веб-клиенте — форма открывается пустой или часть полей не инициализируется, из-за чего возникает подозрение, что обработчик ПриСозданииНаСервере или ПриЧтенииНаСервере пропущен платформой. Дополнительную путаницу вносят особенности взаимодействия клиента и сервера в веб-среде:
Сообщить(), вызванная на сервере, не выводит текст в веб-клиент мгновенно. Платформа накапливает пакеты сообщений и отправляет их клиенту порциями, поэтому при зависании или сбое браузера окно сообщений может остаться пустым.Чтобы гарантированно проверить последовательность исполнения событий без отладчика и системных окон, используем изменение заголовка формы. Этот прием позволяет зафиксировать факт прохождения процедур непосредственно в клиентском окне:
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ЭтаФорма.Заголовок = ЭтаФорма.Заголовок + " [ПриЧтении] " + ТекущаяДата();
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЭтаФорма.Заголовок = ЭтаФорма.Заголовок + " [ПриСоздании] " + ТекущаяДата();
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ЭтаФорма.Заголовок = ЭтаФорма.Заголовок + " [ПриОткрытии] " + ТекущаяДата();
КонецПроцедуры
Если заголовок формы меняется, значит, серверные методы отрабатывают штатно. Проанализируем, где именно скрывается реальная причина сбоя отображения.
Главным источником проблемы является изменение свойства Видимость элементов формы внутри клиентского события ПриАктивизацииСтроки таблицы. Разберем, чем отличается поведение клиентов платформы:
Видимость вызывает полную перестройку ветки DOM-дерева и перерасчет геометрии формы. В процессе перерисовки табличная часть временно теряет и восстанавливает фокус на активной строке. Движок браузера расценивает это как повторный выбор строки пользователем и снова генерирует системное событие активизации.В результате процедура ПриАктивизацииСтроки вызывается повторно, снова меняет видимость элементов и инициирует очередную перерисовку DOM. Возникает бесконечная рекурсия, интерфейс блокируется, а результирующее состояние элементов формы становится непредсказуемым.
Рассмотрим проверенные практические способы устранения этой ошибки.
Наиболее надежный архитектурный подход в управляемом приложении — исключить тяжелые операции перерисовки интерфейса из контекста события активации строки. Перенесем логику управления элементами в отдельную процедуру и запустим ее асинхронно с помощью однократного таймера:
&НаКлиенте
Процедура ТаблицаСписокПриАктивизацииСтроки(Элемент)
// Подключаем однократный обработчик с минимальной задержкой
ПодключитьОбработчикОжидания("ОбновитьОтображениеЭлементов", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьОтображениеЭлементов()
СтрокаТаблицы = Элементы.ТаблицаСписок.ТекущиеДанные;
Если СтрокаТаблицы = Неопределено Тогда
Возврат;
КонецЕсли;
// Управляем интерфейсом вне прямого потока событий таблицы
Элементы.ГруппаДополнительно.Видимость = СтрокаТаблицы.РазныеСроки;
КонецПроцедуры
В данном сценарии событие ПриАктивизацииСтроки завершается мгновенно, браузер завершает расчет выделения строки, и лишь затем управление передается процедуре обновления. Зацикливание полностью исключается.
Если логику требуется оставить внутри самого обработчика, защитим форму от ложных повторных вызовов. Заведем клиентскую переменную для фиксации идентификатора последней обработанной строки:
&НаКлиенте
Перем ПредыдущаяСтрокаТаблицы;
&НаКлиенте
Процедура ТаблицаСписокПриАктивизацииСтроки(Элемент)
ТекущаяСтрока = Элементы.ТаблицаСписок.ТекущаяСтрока;
// Если событие вызвано повторно для той же строки — выходим
Если ТекущаяСтрока = ПредыдущаяСтрокаТаблицы Тогда
Возврат;
КонецЕсли;
ПредыдущаяСтрокаТаблицы = ТекущаяСтрока;
СтрокаДанных = Элементы.ТаблицаСписок.ТекущиеДанные;
Если СтрокаДанных <> Неопределено Тогда
Элементы.ПолеСрок.Видимость = СтрокаДанных.РазныеСроки;
КонецЕсли;
КонецПроцедуры
Благодаря проверке ТекущаяСтрока = ПредыдущаяСтрокаТаблицы повторные импульсы, возникающие при перестроении DOM в веб-клиенте, сразу пресекаются оператором Возврат.
Частая ошибка разработчиков — безусловная перезапись свойств интерфейса на каждом шаге. Даже если строка изменилась, требуемое состояние видимости элементов могло остаться прежним. Исключим лишние перерисовки простой проверкой:
&НаКлиенте
Процедура ОбновитьВидимостьПоля(ЭлементФормы, Знач НоваяВидимость)
Если ЭлементФормы.Видимость <> НоваяВидимость Тогда
ЭлементФормы.Видимость = НоваяВидимость;
КонецЕсли;
КонецПроцедуры
Если свойство элемента уже установлено в нужное булево значение, платформе не придется перерисовывать структуру формы в браузере.
Чтобы приложение гарантированно стабильно работало в любых браузерах, проанализируем альтернативные способы адаптации интерфейса:
Видимость на Доступность или ТолькоПросмотр. Свойства Доступность и ТолькоПросмотр блокируют редактирование реквизитов, но не удаляют теги из структуры DOM и не вызывают пересчет размеров окружающей таблицы, предотвращая сброс фокуса строки.ТекущаяСтраница: переключение страниц оптимизировано веб-клиентом и не вызывает рекурсивных событий.