Front-end (JS)
Glossary Item Box
Базовые JS-классы и внешние библиотеки
Рис. 1. Схема front-end ядра
Внешние библиотеки
ExtJS — представляет собой JavaScript-фреймворк для разработки веб-приложений и пользовательских интерфейсов. Этот фреймворк предназначен в первую очередь для создания сложных и насыщенных интерфейсов. В Creatio ExtJS используется как механизм создания структуры классов клиентской части ядра. Использование фреймворка позволяет реализовать объектно-ориентированный подход, который в чистом виде не реализован в JavaScript. Предоставляет возможность создавать классы, реализовывать иерархию наследования, группировать классы в пространства имен.
RequireJS — библиотека, которая предназначена для реализации подхода Asynchronous Module Definition (AMD). По сути, подход AMD декларирует механизм определения и асинхронной загрузки модулей и их зависимостей.
Angular — предназначен для разработки одностраничных приложений. Его цель — расширение браузерных приложений на основе MVC-шаблона, а также упрощение тестирования и разработки. В Creatio реализована возможность встраивания кастомных Angular-компонентов с использованием единого ядра Angular.
Базовые JS-классы
Базовые JS-классы — неизменяемая часть системы. Основная задача базовых классов — обеспечение работы клиентских модулей конфигурации. Базовые классы хранятся в виде исполняемых файлов на диске в составе папок приложения. Они определяют функциональность основных объектов системы, элементов управления, перечислений и констант.
Механизм сообщений
Sandbox — компонент ядра, который служит диспетчером при взаимодействии модулей системы. Sandbox предоставляет механизм обмена сообщениями между модулями (методы sandbox.publish() и sandbox.subscribe()) и загрузки модулей по требованию в интерфейс приложения (метод sandbox.load()).
Асинхронное определение модулей
Клиентская часть приложения имеет модульную структуру.
Модуль — это инкапсулированный в обособленный блок набор функциональности, который в свою очередь может использовать другие модули, в качестве зависимостей.
Создание модулей в специфике JavaScript декларируется паттерном программирования "Модуль". Классическим приемом реализации этого паттерна является использование анонимных функций, возвращающих определенное значение (объект, функцию и т.д.), которое ассоциируется с модулем. При этом значение модуля экспортируется в глобальный объект.
Основные недостатки такого подхода заключаются в сложности декларирования и использования модулей-зависимостей для таких модулей:
- В момент выполнения анонимной функции все зависимости модуля уже должны быть загружены ранее.
- Загрузка модулей-зависимостей выполняется через HTML-элемент <script></script> в заголовке страницы, и обращение к ним в дальнейшем осуществляется через имена глобальных переменных. При этом разработчик должен четко представлять и реализовывать порядок загрузки всех модулей-зависимостей.
- Как следствие предыдущего пункта — модули загружаются до начала рендеринга страницы, поэтому в модулях нельзя обращаться к элементам управления страницы для реализации какой-либо пользовательской логики.
Таким образом, это, по сути, означает отсутствие возможностей динамической загрузки модулей, применения какой-либо дополнительной логики при загрузке модулей и т.д. В крупных проектах, каким является Creatio, возникает дополнительная проблема в виде сложности управления большим количеством модулей со многими зависимостями, которые могут перекрывать друг друга.
Для устранения перечисленных выше недостатков в Creatio загрузка модулей и их зависимостей выполняется в соответствии с подходом Asynchronous Module Definition (AMD).
Подход AMD декларирует механизм определения и асинхронной загрузки модулей и их зависимостей, который в процессе работы с системой позволяет подгружать только те данные, которые необходимы для работы в текущий момент. Концепцию AMD поддерживают различные JavaScript-фреймворки. В Creatio для работы с модулями используется загрузчик RequireJS.
Основные принципы работы механизма загрузчика RequireJS:
- Объявление модуля выполняется в специальной функции define(), которая регистрирует функцию-фабрику для инстанцирования модуля, но при этом не загружает его немедленно в момент вызова.
- Зависимости модуля передаются как массив строковых значений, а не через свойства глобального объекта.
- Загрузчик выполняет загрузку всех модулей-зависимостей, переданных в качестве аргументов в define(). Модули загружаются асинхронно, при этом фактически порядок их загрузки определяется загрузчиком произвольно.
- После того как загрузчиком будут загружены все указанные зависимости модуля, будет вызвана функция-фабрика, которая вернет значение модуля. При этом в функцию-фабрику в качестве аргументов будут переданы загруженные модули-зависимости.
Для того чтобы загрузчик мог работать с асинхронным модулем, этот модуль должен быть объявлен в исходном коде с помощью функции define() следующим образом.
define(
ModuleName,
[dependencies],
function (dependencies) {
}
);
Параметры функции define() приведены в таблице 1.
Табл. 1. — Параметры функции define()
Аргумент | Значение |
---|---|
ModuleName |
Строка с именем модуля. Необязательный параметр. Если его не указать, загрузчик самостоятельно присвоит модулю имя в зависимости от его расположения в дереве скриптов приложения. Однако для того чтобы иметь возможность обратиться к модулю из других частей приложения (в том числе для асинхронной загрузки такого модуля как зависимости другого модуля), имя модуля должно быть однозначно определено. |
dependencies |
Массив имен модулей, от которых зависит данный модуль. Необязательный параметр. RequireJS выполняет загрузку всех зависимостей, переданных в массиве. Нужно учитывать, что порядок перечисления зависимостей в массиве dependencies должен соответствовать порядку перечисления параметров, передаваемых в функцию-фабрику. Функция-фабрика будет вызвана только после того, как будут загружены все зависимости, перечисленные в dependencies. Загрузка модулей-зависимостей выполняется асинхронно. |
function(dependencies) |
Анонимная функция-фабрика, которая инстанцирует сам модуль. Обязательный параметр. В качестве аргументов в функцию передаются объекты, которые ассоциируются загрузчиком с модулями-зависимостями, перечисленными в аргументе dependencies. Через эти аргументы осуществляется доступ к свойствам и методам модулей-зависимостей внутри создаваемого модуля. Порядок перечисления модулей в dependencies должен соответствовать порядку аргументов функции-фабрики. Функция-фабрика будет вызвана только после того, как будут загружены все модули-зависимости данного модуля (перечисленные в параметре dependencies). Фабрика должна возвращать значение, которое загрузчик будет ассоциировать как экспортируемое значение создаваемого модуля. В качестве возвращаемого значения могут выступать:
|
Модульная разработка в Creatio
Реализация всей пользовательской функциональности выполняется в клиентских модулях.
Рис. 2. Иерархия модулей в Creatio
Несмотря на некоторые функциональные различия, все клиентские модули Creatio имеют одинаковую структуру описания, которая соответствует формату описания модулей AMD.
define( "ModuleName", ["dependencies"], function(dependencies) { // someMethods… return { moduleObject }; });
Здесь:
- ModuleName — имя модуля;
- dependencies — модули-зависимости, функциональность которых можно использовать в текущем модуле;
- moduleObject — конфигурационный объект созданного модуля.
В Creatio можно выделить несколько разновидностей клиентских модулей:
- невизуальный модуль;
- визуальный модуль.
Невизуальный модуль
Невизуальный модуль содержит в себе реализацию функциональности системы, которая не сопряжена с привязкой данных и отображением их в интерфейсе.
Структура описания невизуального модуля:
define( "ModuleName", ["dependencies"], function(dependencies) { // Методы, реализующие необходимую бизнес-логику. return; });
Примерами невизуальных модулей в системе являются утилитные модули, которые реализуют служебные функции.
Визуальный модуль
Визуальный модуль (модель представления) - используется для создания пользовательских визуальных элементов системы.
К визуальным модулям относятся модули, которые реализуют в системе модели представления (ViewModel) согласно шаблону MVVM. Эти модули инкапсулируют в себе данные, которые отображаются в элементах управлениях графического интерфейса, а также методы работы с этими данными.
Визуальный модуль должен содержать следующие методы:
-
init() — метод инициализации модуля.
Отвечает за инициализацию свойств объекта класса, а также за подписку на сообщения.
-
render(renderTo) — метод отрисовки представления модуля в DOM.
Должен возвращать представление.
Принимает единственный аргумент renderTo — элемент, в который будет вставлено представление объекта модуля.
- destroy() — метод, отвечающий за удаление представления модуля, удаление модели представления, отписку от ранее подписанных сообщений и уничтожение объекта класса модуля
Для создания визуального модуля можно использовать базовые классы ядра. Например, создать в модуле класс-наследник Terrasoft.configuration.BaseModule или Terrasoft.configuration.BaseSchemaModule. Это классы клиентского ядра, в которых в необходимой степени уже реализованы необходимые методы визуального модуля — init(), render(renderTo) и destroy().
Структура описания визуального модуля (наследника базового класса Terrasoft.BaseModule):
define(“ModuleName”, [“dependencies”], function(dependencies) { // Определение класса модуля. Ext.define(“Terrasoft..configuration.className”) { alternateClassName: ”Terrasoft.className” extend: "Terrasoft.BaseModule", … // properties and methods … }; // Создание объекта модуля. return Ext.create(Terrasoft.className) });
Примерами визуальных модулей являются модули, реализующие функциональность элементов управления на странице приложения.
Схема модели представления
Наиболее частыми задачами кастомизации приложения являются создание и доработка основных элементов интерфейса — разделов, страниц, деталей.
Модули этих элементов имеют шаблонизированную структуру и называются схемами моделей представления.
Схема модели представления по своей сути является неким конфигурационным объектом для генерации представления и модели представления генераторами Creatio ViewGenerator и ViewModelGenerator.
Для большинства задач кастомизации в Creatio используется механизм замещения базовых схем. К ним относятся все схемы из предустановленных пакетов конфигурации.
Основные базовые схемы моделей представления:
- BasePageV2
- BaseSectionV2
- BaseDetailV2
Все схемы имеют общую структуру исходного кода:
define(“SchemaName”, [“dependencies”], function(dependencies) { return { entitySchemaName: "ExampleEntity", mixins: {}, attributes: {}, messages: {}, methods: {}, rules: {}, businessRules: {}, modules: {}, diff: [] }; });
Примерами схем представления являются схемы страниц, разделов и деталей.
Обучающее видео