При работе с управляемыми формами в 1С часто возникает задача интеграции веб-технологий с помощью элемента ПолеHTMLДокумента. Это открывает широкие возможности, например, для встраивания сложных редакторов кода, интерактивных карт или дашбордов. Однако здесь кроется проблема производительности: если форма содержит "тяжелый" JavaScript-компонент, его инициализация может занимать ощутимое время, например, несколько секунд.
Рассмотрим ситуацию: у нас есть форма с полем HTML, в котором загружен сложный компонент, например, редактор кода Monaco. При первом открытии все скрипты загружаются и инициализируются. Чтобы при последующих открытиях не тратить время заново, мы решаем не уничтожать объект формы при закрытии, а переиспользовать его. Однако, к нашему удивлению, при каждом новом вызове ОткрытьФорму() платформа все равно заново инициализирует поле HTML-документа, вызывая событие ДокументСформирован() и сбрасывая все внутреннее состояние компонента. Как можно этого избежать?
Прежде чем искать решение, давайте разберемся в корне проблемы. Основная причина кроется в жизненном цикле элементов управления на форме 1С. Когда форма становится невидимой, а затем отображается снова, платформа может пересоздавать "тяжелые" нативные элементы управления для оптимизации ресурсов.
Ключевой момент: Платформа "1С:Предприятие" при каждом отображении формы, даже если сам объект формы в памяти не уничтожался, пересоздает сам элемент управления, в котором работает браузерный движок (WebKit). Это не просто вызов события, а полная перезагрузка встроенного браузера. Как следствие:
ДокументСформирован() на стороне 1С.Именно поэтому простые подходы, которые первыми приходят в голову, не работают:
ДокументСформирован(). Проверка вроде "Если не ПерваяИнициализация Тогда Возврат; КонецЕсли;" бесполезна, так как сам JavaScript-контекст каждый раз новый.Видимость = Ложь или высоту/ширину в 0), платформа все равно уничтожает объект браузера и при обратном включении видимости создает его заново.Прямого способа "заморозить" состояние поля HTML-документа платформа не предоставляет. Поэтому решение задачи сводится не к предотвращению переинициализации, а к минимизации ее последствий. Рассмотрим несколько рабочих подходов.
Этот метод не предотвращает перезагрузку, но позволяет значительно ускорить восстановление состояния компонента до того вида, в котором он был перед закрытием формы.
Суть подхода: перед закрытием формы мы "выгружаем" все важное состояние из JavaScript в реквизиты формы 1С, а при следующей инициализации "загружаем" его обратно.
Разберем по шагам:
Создаем реквизит для хранения состояния. В реквизитах формы создадим реквизит, например, СостояниеHTML, с типом ХранилищеЗначения или Строка неограниченной длины (если состояние можно сериализовать в JSON).
Организуем передачу данных из JavaScript в 1С. В JavaScript-коде вашего компонента нужно реализовать функцию, которая собирает все необходимые данные (текст, настройки, позицию курсора и т.д.) и передает их в 1С. Для этого используется стандартный механизм взаимодействия:
// Пример на JavaScript
function saveState() {
const editorState = {
text: myEditor.getValue(),
cursorPosition: myEditor.getPosition()
};
// Вызываем процедуру 1С, объявленную на форме
window.notify('СохранитьСостояние', JSON.stringify(editorState));
}
Этот JavaScript-код нужно вызывать в подходящий момент, например, по событию onbeforeunload веб-страницы или принудительно из 1С перед закрытием формы.
Принимаем и сохраняем состояние в 1С. На форме 1С создаем экспортную процедуру, которая будет принимать данные, и обработчик события ПриЗакрытии, который инициирует сохранение.
// Код в модуле формы 1С
&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
// Перед закрытием даем команду JS сохранить состояние
Элементы.ПолеHTML.ВыполнитьДействие("saveState()");
КонецПроцедуры
&НаКлиенте
Процедура СохранитьСостояние(Данные) Экспорт
// Получаем JSON от JavaScript и сохраняем в реквизит формы
ЭтотОбъект.СостояниеHTML = Данные;
КонецПроцедуры
Восстанавливаем состояние при новой инициализации. Теперь в обработчике ДокументСформирован() мы можем быстро восстановить компонент.
// Код в модуле формы 1С
&НаКлиенте
Процедура ПолеHTMLДокументСформирован(Элемент)
Если ЗначениеЗаполнено(ЭтотОбъект.СостояниеHTML) Тогда
// Если есть сохраненное состояние, передаем его в JS
// для быстрой инициализации
ДанныеДляВосстановления = ЭтотОбъект.СостояниеHTML;
Элементы.ПолеHTML.ВыполнитьДействие("restoreState('" + ДанныеДляВосстановления + "')");
Иначе
// Логика первой инициализации
КонецЕсли;
КонецПроцедуры
В JavaScript, соответственно, должна быть функция restoreState, которая примет JSON и применит его к компоненту.
Итог по методу: Мы все еще тратим время на инициализацию самой библиотеки (Monaco и т.д.), но мгновенно восстанавливаем пользовательские данные и настройки, что делает "просадку" производительности гораздо менее заметной.
Этот подход переносит логику сохранения состояния полностью на сторону веб-технологий и может быть более элегантным, если тесная связь с данными 1С не требуется.
Суть подхода: JavaScript-компонент самостоятельно сохраняет свое состояние во встроенное хранилище браузера (localStorage) и сам же его оттуда читает при инициализации.
Как это работает:
Сохранение состояния в JavaScript. В коде вашего HTML-документа добавляем логику, которая по мере изменения данных (например, при вводе текста) сохраняет их в localStorage.
// Пример на JavaScript
// myEditor - это ваш объект редактора
myEditor.onDidChangeModelContent(() => {
// При каждом изменении контента сохраняем его
const currentState = myEditor.getValue();
localStorage.setItem('myEditorContent', currentState);
});
Восстановление состояния при загрузке. При инициализации скрипта мы сначала проверяем, есть ли что-то в localStorage. Если есть — используем эти данные.
// Пример на JavaScript
document.addEventListener('DOMContentLoaded', () => {
const savedContent = localStorage.getItem('myEditorContent');
// Инициализируем редактор
const myEditor = monaco.editor.create(document.getElementById('container'), {
value: savedContent || '// Введите ваш код здесь', // Если есть сохраненные данные - используем их
language: 'bsl'
});
// ... остальной код инициализации и подписки на события сохранения
});
Преимущества:
Недостатки:
Проблема переинициализации поля HTML-документа в 1С является фундаментальным ограничением платформы, обойти которое напрямую невозможно. Однако, поняв причину, мы можем применить эффективные обходные пути. Выбор между кэшированием состояния на стороне 1С и использованием localStorage зависит от конкретной задачи:
localStorage будет проще и элегантнее.В любом случае, ключ к решению — это не борьба с пересозданием объекта, а быстрая и автоматическая подгрузка его последнего состояния в момент новой инициализации.