К статье
Практический материал

Разработка и Конфигурация · 11 мин

НаКлиенте в 1С: что это и как работает директива

Директива НаКлиенте в 1С: что означает, где выполняется код, чем отличается от НаСервере, ограничения, типичные ошибки и примеры использования в модулях форм.

«НаКлиенте» — это директива компиляции встроенного языка 1С:Предприятие, которая указывает, что процедура или функция должна выполняться на стороне клиентского приложения, а не на сервере. Она записывается в виде амперсанда перед объявлением: &НаКлиенте. Такой код работает в контексте компьютера пользователя — в тонком клиенте, толстом клиенте или веб-клиенте — и имеет доступ только к тем данным и объектам, которые доступны в клиентском контексте.

Директива появилась вместе с управляемыми формами и управляемым приложением в платформе 8.2. До этого весь код формы исполнялся в одном месте, и разработчик не задумывался о разделении. В управляемом приложении архитектура стала клиент-серверной: форма отображается на клиенте, а данные хранятся и обрабатываются на сервере. Поэтому каждую процедуру модуля формы нужно явно отнести к одной из сторон.

Понимание директив компиляции — базовый навык для разработчика управляемых форм. Ошибки в выборе контекста приводят к типовым сообщениям вида «Процедура или функция с указанным именем не определена», «Переменная не определена» или «Использование модального окна в данном режиме запрещено». Ниже разберём, как устроено разделение, какие ограничения есть у клиентского кода и как правильно организовать взаимодействие клиента и сервера.

Что означает директива НаКлиенте

Директива &НаКлиенте ставится непосредственно перед ключевым словом «Процедура» или «Функция» в модуле управляемой формы. Она сообщает компилятору, в каком контексте нужно собрать этот фрагмент кода. Без директивы процедура в модуле управляемой формы вообще не скомпилируется — платформа выдаст ошибку ещё на этапе проверки модуля.

Клиентский контекст — это среда исполнения на рабочем месте пользователя. Здесь доступны элементы формы, реквизиты формы, данные текущей строки табличной части, стандартные диалоги (выбор файла, вопрос, предупреждение), а также средства работы с файловой системой компьютера пользователя. Именно поэтому обработчики событий формы — ПриНажатии, ПриИзменении, ПриАктивизацииСтроки — практически всегда объявляются с директивой НаКлиенте.

Какие директивы существуют и чем они отличаются

В модуле управляемой формы используются четыре основные директивы. Их выбор определяет не только место исполнения, но и набор доступных объектов и возможность вызова из других контекстов.

ДирективаГде выполняетсяДоступ к БД и запросамТипичное применение
&НаКлиентеКлиентское приложениеНетОбработчики событий, работа с интерфейсом, файлами, диалогами
&НаСервереСервер 1СДаЗапросы, чтение и запись объектов, проведение документов
&НаСервереБезКонтекстаСервер, без данных формыДаУниверсальные серверные функции, не требующие реквизитов формы
&НаКлиентеНаСервереБезКонтекстаИ там, и тамНетВспомогательные расчёты над переданными параметрами

Ключевое различие — между НаКлиенте и НаСервере. Клиентский код не может выполнить запрос к базе данных, обратиться к менеджеру объекта (например, Справочники.Номенклатура) или использовать объектные методы записи. Попытка сделать это приведёт к ошибке компиляции или выполнения, потому что на клиенте этих типов просто не существует.

Директива НаСервереБезКонтекста выгодна с точки зрения производительности: при её вызове на сервер не передаётся весь объект формы с реквизитами и табличными частями. Передаются только явно указанные параметры. Для форм с большими таблицами это заметно снижает объём трафика между клиентом и сервером.

Сравнение вариантов

НаКлиенте

Подходит для реакции на действия пользователя и работы с интерфейсом. Ограничение: нет доступа к базе данных и запросам.

НаСервере

Подходит для работы с данными формы и объектами базы. Ограничение: данные формы сериализуются при каждом вызове, что дорого на больших формах.

НаСервереБезКонтекста

Подходит для массовых операций и чтения данных. Ограничение: нельзя напрямую обратиться к реквизитам формы, их нужно передавать параметрами.

Что можно и чего нельзя делать в клиентском коде

В процедурах с директивой НаКлиенте доступна вся модель формы: элементы, реквизиты, команды, свойства текущих данных табличных частей. Здесь же работают методы интерактивного взаимодействия — ПоказатьВопрос, ПоказатьПредупреждение, ОткрытьФорму, диалоги выбора файлов, а также работа с файловой системой через расширение работы с файлами.

Запрещены и физически недоступны: построитель запросов и объект Запрос, менеджеры прикладных объектов (Справочники, Документы, РегистрыСведений и т.д.), объектные методы записи и проведения, прямой доступ к транзакциям. Также в тонком и веб-клиенте запрещены модальные вызовы старого стиля — Вопрос(), Предупреждение() без обработчика оповещения; вместо них используются немодальные аналоги с описанием оповещения.

Как организовать вызов сервера из клиентского кода

Типовой сценарий выглядит так: пользователь изменил поле формы, сработал клиентский обработчик, который собрал нужные значения реквизитов и вызвал серверную процедуру. Серверная процедура выполнила запрос, обработала данные и вернула результат — примитивное значение, структуру или массив. Клиентская процедура получила результат и обновила интерфейс.

&НаКлиенте

Процедура КонтрагентПриИзменении(Элемент)

Если ЗначениеЗаполнено(Объект.Контрагент) Тогда

РеквизитыКонтрагента = ПолучитьРеквизитыКонтрагента(Объект.Контрагент);

Объект.ИНН = РеквизитыКонтрагента.ИНН;

КонецЕсли;

КонецПроцедуры

&НаСервереБезКонтекста

Функция ПолучитьРеквизитыКонтрагента(Контрагент)

Возврат ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Контрагент, "ИНН");

КонецФункции

Обратите внимание: ссылка на контрагента передаётся на сервер как параметр — это допустимо, ссылки сериализуются корректно. А вот вернуть с сервера на клиент объект базы данных или набор записей нельзя: передаваться могут только сериализуемые типы. Для таблиц значений на клиенте используется тип ДанныеФормыКоллекция или массив структур.

Порядок действий при разделении кода
  1. 1
    Определите, где должна выполняться логика: интерфейс — клиент, данные — сервер
  2. 2
    Объявите клиентский обработчик события с директивой НаКлиенте
  3. 3
    Создайте серверную процедуру НаСервереБезКонтекста и передайте в неё только нужные параметры
  4. 4
    Верните из сервера результат сериализуемого типа
  5. 5
    Обновите реквизиты формы в клиентской процедуре по результату
  6. 6
    Проверьте форму в тонком клиенте и при необходимости в веб-клиенте

Типичные ошибки и ограничения

Самая частая ошибка — обращение к запросу или менеджеру объекта прямо в клиентской процедуре. Модуль может даже сохраниться, если проверка отключена, но при выполнении пользователь получит ошибку. Вторая по частоте — использование модальных методов: конфигурации, работающие в веб-клиенте, должны применять только немодальные вызовы с описаниями оповещений.

Ещё одна группа проблем — избыточные серверные вызовы. Если клиентский обработчик ПриИзменении дергает сервер на каждое нажатие клавиши, форма начинает заметно тормозить, особенно при медленном канале. Решение — кэшировать данные на клиенте, объединять несколько обращений в один вызов и переносить простые проверки (заполненность, формат) на клиентскую сторону.

Типичные ошибки
01
Запрос к базе в процедуре НаКлиенте — ошибка выполнения у пользователя
02
Модальный Вопрос() вместо ПоказатьВопрос с оповещением — не работает в веб-клиенте
03
Серверный вызов на каждое событие ввода — форма тормозит из-за постоянных обращений к серверу
04
Попытка вернуть с сервера объект базы вместо структуры — ошибка сериализации
05
Проверка модуля только в толстом клиенте — в тонком клиенте часть кода недоступна

Как проверить, что разделение контекстов сделано правильно

Первый уровень контроля — проверка модулей в конфигураторе с включёнными режимами «Тонкий клиент» и «Веб-клиент». Конфигуратор покажет недоступные в этих контекстах вызовы ещё до запуска. Второй уровень — реальное тестирование формы в тонком клиенте: именно там всплывают ошибки, которые толстый клиент прощает, потому что исполняет больше кода локально.

Также полезно оценить количество серверных вызовов. В технологическом журнале или через замеры производительности видно, сколько раз форма обращается к серверу при типовом сценарии. Если простое открытие формы порождает десятки вызовов, стоит пересмотреть архитектуру обработчиков.

Контрольные точки

Как проверить результат

Проверка модуля в конфигураторе
Норма

Нет ошибок в режимах тонкого и веб-клиента

Тревожный признак

Ошибки о недоступных типах и методах

Работа формы в тонком клиенте
Норма

Все операции выполняются без сообщений об ошибках

Тревожный признак

Ошибки о неопределённых процедурах или недоступных методах

Количество серверных вызовов
Норма

Один-два вызова на типовое действие пользователя

Тревожный признак

Вызов на каждое событие ввода, заметные паузы

При сомнениях, куда поместить процедуру, задайте себе вопрос: нужны ли ей данные из базы? Если да — сервер, если речь только о том, что уже есть на форме, — клиент. Это правило закрывает большинство ситуаций и не требует запоминания списков доступных типов.
ПЗ
Практическое замечание

FAQ по директиве НаКлиенте

Можно ли вызвать клиентскую процедуру из серверной?

Нет, прямой вызов с сервера на клиент невозможен — сервер не знает о состоянии конкретного клиентского приложения. Обратная связь реализуется через возвращаемые значения серверных процедур: клиент вызывает сервер, получает результат и сам решает, что обновить в интерфейсе.

Почему в модуле формы нельзя объявить процедуру без директивы?

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

Чем НаКлиентеНаСервереБезКонтекста отличается от НаКлиенте?

Такая процедура компилируется в обоих контекстах и может вызываться откуда угодно, но поэтому в ней доступны только типы, существующие и на клиенте, и на сервере. Запросы недоступны, как и специфика формы. Подходит для чистых вычислений над параметрами — например, расчёта суммы строки.

Работает ли НаКлиенте в обычных формах?

Нет. В обычном приложении весь модуль формы исполняется на клиенте, и директивы компиляции там не используются. Директивы актуальны только для управляемых форм и управляемого режима работы.

Как передать на сервер табличную часть документа из формы?

Либо используйте процедуру НаСервере с контекстом — тогда данные формы передадутся автоматически, либо в НаСервереБезКонтекста передайте ссылку на объект и прочитайте табличную часть на сервере, либо выгрузите данные в массив структур и передайте параметром. Первый вариант проще, второй и третий — эффективнее по трафику.

Почему в веб-клиенте не работает код, который работает в тонком?

Веб-клиент исполняется в браузере и имеет более узкий набор доступных средств: ограничена работа с файловой системой, недоступны некоторые COM- и OLE-механизмы, строже требования к немодальности. Проверяйте функциональность во всех целевых клиентах, а файловые операции выполняйте через расширение работы с файлами.

Итог

Что важно запомнить

НаКлиенте — директива, размещающая код на стороне клиентского приложения. Клиент отвечает за интерфейс и диалоги, сервер — за данные и запросы. Правильное разделение контекстов, немодальные вызовы и минимум серверных обращений дают устойчивые и быстрые управляемые формы.