Как заблокировать повторную инициализацию поля HTML-документа при открытии формы в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с управляемыми формами в 1С часто возникает задача интеграции веб-технологий с помощью элемента ПолеHTMLДокумента. Это открывает широкие возможности, например, для встраивания сложных редакторов кода, интерактивных карт или дашбордов. Однако здесь кроется проблема производительности: если форма содержит "тяжелый" JavaScript-компонент, его инициализация может занимать ощутимое время, например, несколько секунд.

Рассмотрим ситуацию: у нас есть форма с полем HTML, в котором загружен сложный компонент, например, редактор кода Monaco. При первом открытии все скрипты загружаются и инициализируются. Чтобы при последующих открытиях не тратить время заново, мы решаем не уничтожать объект формы при закрытии, а переиспользовать его. Однако, к нашему удивлению, при каждом новом вызове ОткрытьФорму() платформа все равно заново инициализирует поле HTML-документа, вызывая событие ДокументСформирован() и сбрасывая все внутреннее состояние компонента. Как можно этого избежать?

Анализ проблемы: почему происходит переинициализация?

Прежде чем искать решение, давайте разберемся в корне проблемы. Основная причина кроется в жизненном цикле элементов управления на форме 1С. Когда форма становится невидимой, а затем отображается снова, платформа может пересоздавать "тяжелые" нативные элементы управления для оптимизации ресурсов.

Ключевой момент: Платформа "1С:Предприятие" при каждом отображении формы, даже если сам объект формы в памяти не уничтожался, пересоздает сам элемент управления, в котором работает браузерный движок (WebKit). Это не просто вызов события, а полная перезагрузка встроенного браузера. Как следствие:

  1. Происходит полная перезагрузка HTML-документа и всех связанных с ним скриптов и стилей.
  2. Срабатывает событие ДокументСформирован() на стороне 1С.
  3. Теряется все внутреннее состояние JavaScript: значения глобальных переменных, введенный пользователем текст, история изменений (undo/redo), положение курсора и т.д.

Именно поэтому простые подходы, которые первыми приходят в голову, не работают:

Прямого способа "заморозить" состояние поля HTML-документа платформа не предоставляет. Поэтому решение задачи сводится не к предотвращению переинициализации, а к минимизации ее последствий. Рассмотрим несколько рабочих подходов.

Решение 1: Кэширование состояния на стороне 1С

Этот метод не предотвращает перезагрузку, но позволяет значительно ускорить восстановление состояния компонента до того вида, в котором он был перед закрытием формы.

Суть подхода: перед закрытием формы мы "выгружаем" все важное состояние из JavaScript в реквизиты формы 1С, а при следующей инициализации "загружаем" его обратно.

Разберем по шагам:

  1. Создаем реквизит для хранения состояния. В реквизитах формы создадим реквизит, например, СостояниеHTML, с типом ХранилищеЗначения или Строка неограниченной длины (если состояние можно сериализовать в JSON).

  2. Организуем передачу данных из JavaScript в 1С. В JavaScript-коде вашего компонента нужно реализовать функцию, которая собирает все необходимые данные (текст, настройки, позицию курсора и т.д.) и передает их в 1С. Для этого используется стандартный механизм взаимодействия:

    
    // Пример на JavaScript
    function saveState() {
        const editorState = {
            text: myEditor.getValue(),
            cursorPosition: myEditor.getPosition()
        };
        // Вызываем процедуру 1С, объявленную на форме
        window.notify('СохранитьСостояние', JSON.stringify(editorState));
    }
    

    Этот JavaScript-код нужно вызывать в подходящий момент, например, по событию onbeforeunload веб-страницы или принудительно из 1С перед закрытием формы.

  3. Принимаем и сохраняем состояние в 1С. На форме 1С создаем экспортную процедуру, которая будет принимать данные, и обработчик события ПриЗакрытии, который инициирует сохранение.

    
    // Код в модуле формы 1С
    
    &НаКлиенте
    Процедура ПриЗакрытии(ЗавершениеРаботы)
        // Перед закрытием даем команду JS сохранить состояние
        Элементы.ПолеHTML.ВыполнитьДействие("saveState()");
    КонецПроцедуры
    
    &НаКлиенте
    Процедура СохранитьСостояние(Данные) Экспорт
        // Получаем JSON от JavaScript и сохраняем в реквизит формы
        ЭтотОбъект.СостояниеHTML = Данные;
    КонецПроцедуры
    
  4. Восстанавливаем состояние при новой инициализации. Теперь в обработчике ДокументСформирован() мы можем быстро восстановить компонент.

    
    // Код в модуле формы 1С
    
    &НаКлиенте
    Процедура ПолеHTMLДокументСформирован(Элемент)
        Если ЗначениеЗаполнено(ЭтотОбъект.СостояниеHTML) Тогда
            // Если есть сохраненное состояние, передаем его в JS
            // для быстрой инициализации
            ДанныеДляВосстановления = ЭтотОбъект.СостояниеHTML;
            Элементы.ПолеHTML.ВыполнитьДействие("restoreState('" + ДанныеДляВосстановления + "')");
        Иначе
            // Логика первой инициализации
        КонецЕсли;
    КонецПроцедуры
    

    В JavaScript, соответственно, должна быть функция restoreState, которая примет JSON и применит его к компоненту.

Итог по методу: Мы все еще тратим время на инициализацию самой библиотеки (Monaco и т.д.), но мгновенно восстанавливаем пользовательские данные и настройки, что делает "просадку" производительности гораздо менее заметной.

Решение 2: Использование веб-хранилища (localStorage)

Этот подход переносит логику сохранения состояния полностью на сторону веб-технологий и может быть более элегантным, если тесная связь с данными 1С не требуется.

Суть подхода: JavaScript-компонент самостоятельно сохраняет свое состояние во встроенное хранилище браузера (localStorage) и сам же его оттуда читает при инициализации.

Как это работает:

  1. Сохранение состояния в JavaScript. В коде вашего HTML-документа добавляем логику, которая по мере изменения данных (например, при вводе текста) сохраняет их в localStorage.

    
    // Пример на JavaScript
    // myEditor - это ваш объект редактора
    
    myEditor.onDidChangeModelContent(() => {
        // При каждом изменении контента сохраняем его
        const currentState = myEditor.getValue();
        localStorage.setItem('myEditorContent', currentState);
    });
    
  2. Восстановление состояния при загрузке. При инициализации скрипта мы сначала проверяем, есть ли что-то в 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 зависит от конкретной задачи:

В любом случае, ключ к решению — это не борьба с пересозданием объекта, а быстрая и автоматическая подгрузка его последнего состояния в момент новой инициализации.

← На главную