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

Сегодня я хотел бы поделиться своим опытом в области проектирования крупномасштабной архитектуры внешнего интерфейса и способов ее реализации в SAP UI5. Итак, будут две темы: 1. Общий дизайн крупномасштабной архитектуры внешнего интерфейса. 2. Как реализовать это в SAP UI5.

Часть 1. Общее проектирование крупномасштабной внешней архитектуры.

Все хорошие приложения должны быть:

  1. Легко модифицировать и расширять.
  2. Несколько команд могут легко работать над ним одновременно, не беспокоясь о том, чтобы испортить другую часть приложения.
  3. Людям легко понять дизайн.

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

Модульный дизайн повсюду в нашей повседневной жизни. Я бы хотел взять для примера модульный аппаратный компьютер:

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

  • Контейнер приложения создает и отображает другой модуль по мере необходимости. Контейнер приложения только этого не делает.
  • Каждый модуль не должен знать друг друга.
  • На глобальном уровне должен быть механизм связи 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 выполняет две функции:

  1. ModularRouter добавляет префикс к шаблону маршрута модуля во время выполнения. Значение префикса передается создателем модуля, в данном случае ApplicationContainer.
  2. 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

  1. Поскольку шаблон маршрута ApplicationContainer - «{module} &: all *:», шаблон будет соответствовать, а параметр {module} - «student». ApplicationContainer создаст и отобразит модуль Student на основе параметра {module}.
  2. Затем создается Студенческий модуль. шаблон маршрута редактирования был «edit / {id}», но из-за routePatternPrefix, который мы определили в manifest.json, его шаблон маршрута во время выполнения теперь имеет вид «student & / edit / { я бы}". Бинго, теперь этот URL-адрес будет сопоставлен для редактирования маршрута без конфликтов!

2.5 Навигация между модулями

Модули не знают друг друга. Но что, если вам нужно перейти от модуля A к модулю B? Мы используем SAP EventBus для межмодульной связи. Модуль A публикует событие в ApplicationContainer. Затем ApplicationContainer визуализирует целевой модуль B.