Немного обо мне, я ведущий фронтенд-разработчик в SAP. За свою карьеру я работал над множеством масштабных и сложных клиентских приложений. Я начал свой путь к SAP UI5 несколько лет назад. Приглашаем подписаться на меня в linkedin https://www.linkedin.com/in/haojia и GitHub haojia321.
Сегодня я хотел бы поделиться своим опытом в области проектирования крупномасштабной архитектуры внешнего интерфейса и способов ее реализации в SAP UI5. Итак, будут две темы: 1. Общий дизайн крупномасштабной архитектуры внешнего интерфейса. 2. Как реализовать это в SAP UI5.
Часть 1. Общее проектирование крупномасштабной внешней архитектуры.
Все хорошие приложения должны быть:
- Легко модифицировать и расширять.
- Несколько команд могут легко работать над ним одновременно, не беспокоясь о том, чтобы испортить другую часть приложения.
- Людям легко понять дизайн.
Я делаю это, разделяя приложение на несколько модулей и абстрагируя логику приложения на разные уровни.
Модульный дизайн повсюду в нашей повседневной жизни. Я бы хотел взять для примера модульный аппаратный компьютер:

Внутри корпуса ПК находится множество компонентов: ЦП, жесткий диск, видеокарта, вентиляторы кулера и т. Д. Если я считаю, что центральный процессор является узким местом производительности моего компьютера, я могу просто купить лучший ЦП, чтобы заменить старый. Это легко и быстро. Мне не нужно беспокоиться о том, что это сломает другие компоненты ПК. А теперь вернемся к нашему миру фронтенда. Как определить, какие части мне следует поместить в модуль. Ну, это зависит от обстоятельств, но я рекомендую вам объединить эти тесно связанные страницы пользовательского интерфейса в один модуль. Схема должна быть примерно такой:


- Контейнер приложения создает и отображает другой модуль по мере необходимости. Контейнер приложения только этого не делает.
- Каждый модуль не должен знать друг друга.
- На глобальном уровне должен быть механизм связи EventBus. Каждый модуль может общаться только через EventBus.
- Компонент пользовательского интерфейса имеет меньшую степень детализации по сравнению с модульным дизайном. Компонент пользовательского интерфейса должен быть общим элементом пользовательского интерфейса, который можно повторно использовать во всех модулях. Это может быть кнопка, список или всплывающее окно с предупреждением и т. Д. Вот хорошее руководство по компонентам пользовательского интерфейса.
Часть 2. Как реализовать это в Open UI5 или SAP UI5

Предварительным условием для этой части является наличие базовых знаний об открытой платформе UI5 или SAP UI5. Если вы этого не сделаете, я настоятельно рекомендую вам остановиться на этом и сначала ознакомиться с документацией Open UI5.
2.1 Обзор

Я создал демо на github, чтобы продемонстрировать реализацию. В этой демонстрации я создал модуль ApplicationContainer и два дочерних модуля: Student и Exam.
- В модуле «Студент» есть две страницы: редактировать студента и искать студента.
- Модуль экзамена состоит из двух страниц: редактировать экзамен и искать экзамен.
- ApplicationContainer имеет строку меню и основную область отображения.
- ApplicationContainer имеет только один шаблон маршрута: «{module} &: all *:». Он уместится на всех страницах. Все, что он делает, это загружает модули по мере необходимости и отображает их в соответствующей области пользовательского интерфейса.
- Каждый модуль будет отображаться в основной области отображения по запросу после того, как пользователь щелкнет ссылку в строке меню.
- Чтобы упростить демонстрацию, каждый раз в основной области отображения может отображаться только один модуль. Другие модули можно отобразить в основной области отображения, но они будут просто скрыты.

2.2 Как собрать модуль
UI5 рекомендует использовать UIComponent.js и manifest.json для настройки проекта. Моя реализация следует за ним. [ПРИМЕЧАНИЕ: UIComponent.js в UI5 - это концепция, отличная от дизайна компонента UI, который мы упоминали в части 1. Соответствующая терминология называется UI Control в UI5. SAP UI5 имеет очень надежную библиотеку управления пользовательским интерфейсом.]
Я использовал UIComponent.js для реализации дизайна модуля. Преимущества UIComponent.js:
- Он изолирован от других модулей на уровне фреймворка.
- Его можно легко заменить, как будто вы подключаете / отключаете USB-накопитель.
- Каждый модуль загружает свой собственный файл css и метки i18n.
- Каждый модуль объединяет свои собственные файлы ресурсов, что обеспечивает лучшую производительность сети.
- Каждый модуль можно протестировать отдельно.
2.3 Как визуализировать и отобразить модуль в ApplicationContainer
Я создал элемент управления ComponentLoader. ApplicationContainer составляет ComponentLoader. Он использует ComponentLoader для рендеринга и отображения соответствующего компонента в конкретном DIV / элементе управления. Пожалуйста, проверьте мой демонстрационный код для получения более подробной информации.
2.4 Навигация
UI5 использует шаблон маршрута для представления URL-адреса браузера. Давайте внимательно посмотрим на шаблоны маршрутов:
- У студенческого модуля есть 2 маршрута и шаблоны: «edit / {id}» и «studentSearch».
- Модуль экзамена имеет 2 маршрута и шаблоны: «редактировать / {id}» и «искать».
- ApplicationContainer имеет только один шаблон «{module} &: all *:»
Как видите, и в модуле «Студент», и в модуле «Экзамен» есть шаблон маршрута «edit / {id}». Поэтому, когда вы вводите «edit / {id}» в адресную строку браузера, ApplicationContainer не знает, какой модуль следует выбрать и инициализировать. Так как же решить эту проблему? Я придумал несколько подходов ниже:
Подход 1:
Согласно документу SAPUI5 вы можете определить родительский маршрут в файле конфигурации маршрута модуля. Но это не очень хорошая идея, потому что этот модуль будет связан с одним конкретным родительским модулем. Это ограничит возможность повторного использования модуля. Дочерний элемент (модуль Студент и экзамен) никогда не должен знать о родителе (ApplicationContainer).
Подход 2 (в демонстрации использовался этот подход):
Итак, я создал новый маршрутизатор под названием ModularRouter, который идет от sap.m.routing.Router. ModularRouter выполняет две функции:
- ModularRouter добавляет префикс к шаблону маршрута модуля во время выполнения. Значение префикса передается создателем модуля, в данном случае ApplicationContainer.
- ModularRouter принимает функцию обратного вызова, которая будет вызываться после инициализации маршрутизатора. Это очень полезно, когда вы хотите что-то сделать после того, как вы создали модуль и отрендерили его на странице.
Давайте не будем смотреть на ApplicationContainer manifest.json:
"sap.ui5": {
"_version": "1.1.0",
"componentUsages": {
"student": {
"name": "com.haojia.test.student",
"componentData": {
"routePatternPrefix": "student&/"
}
},
"exam": {
"name": "com.haojia.test.exam",
"componentData": {
"routePatternPrefix": "exam&/"
}
}
},
"dependencies": {
"minUI5Version": "1.30",
"libs": {
"sap.m": {}
},
"components": {
"com.haojia.test.student": {}
}
},
"rootView": "com.haojia.test.applicationContainer.view.App",
"routing": {
"config": {
"routerClass": "com.haojia.test.util.ModularRouter",
"viewType": "XML",
"viewPath": "com.haojia.test.adminLayout.view",
"transition": "show",
"controlId": "app",
"clearTarget": true,
"controlAggregation": "pages"
},
"routes": [{
"name": "App",
"pattern": "{module}&:all*:"
}]
}
}
Обратите внимание на жирный текст. В качестве родительского модуля он определяет модуль Student как зависимость. И передает routePatternPrefix через componentData. Поступая таким образом, мы можем динамически добавлять префикс к шаблону маршрута для решения проблемы конфликтов нескольких шаблонов модулей.
Каждый модуль имеет свой собственный маршрутизатор и определение шаблона. Но панель URL-адресов браузера глобальна для каждого модуля. Итак, как уже было сказано, один URL может соответствовать нескольким модулям. Таким образом, возможно, что шаблон X может быть сопоставлен ApplicationContainer и модулем Student одновременно. Чтобы использовать это, ApplicationContainer имеет только один шаблон маршрута: «{module} &: all *:». Это нечеткое сопоставление с образцом, которое будет соответствовать каждому модулю.
Давайте возьмем реальный пример URL, предположим, что текущий URL в адресной строке браузера - http: //www.haojia.space#/student&/edit/abc
- Поскольку шаблон маршрута ApplicationContainer - «{module} &: all *:», шаблон будет соответствовать, а параметр {module} - «student». ApplicationContainer создаст и отобразит модуль Student на основе параметра {module}.
- Затем создается Студенческий модуль. шаблон маршрута редактирования был «edit / {id}», но из-за routePatternPrefix, который мы определили в manifest.json, его шаблон маршрута во время выполнения теперь имеет вид «student & / edit / { я бы}". Бинго, теперь этот URL-адрес будет сопоставлен для редактирования маршрута без конфликтов!
2.5 Навигация между модулями
Модули не знают друг друга. Но что, если вам нужно перейти от модуля A к модулю B? Мы используем SAP EventBus для межмодульной связи. Модуль A публикует событие в ApplicationContainer. Затем ApplicationContainer визуализирует целевой модуль B.