Урок 2. SAPUI5. Model View Controller. Модуляризация.
SAPUI5 поддерживает схему Model View Controller. Мы разделяем данных приложения, пользовательского интерфейса и управляющей логики на три отдельных компонента: модель (Model), представление (View) и контроллер (Controller) — таким образом, мы можем делать изменения в одном компоненте, не изменяя другой компонент (модификация каждого компонента может осуществляться независимо).
Главная задача MVC — отделении бизнес-логики (модели) от её визуализации (представления).
- Модель (Model) предоставляет данные и методы работы с ними: запросы в базу данных, проверка на корректность.
Модель не зависит от представления — не знает как данные визуализировать — и контроллера — не имеет точек взаимодействия с пользователем — просто предоставляя доступ к данным и управлению ими. - Представление (View) отвечает за получение необходимых данных и визуализацию (отображение на экране пользователю) данных модели, реагируя на изменения модели.
- Контроллер (Controller) отвечает за обработку действий пользователя, оповещая модель о необходимости изменений.
Контроллер связывает между собой пользователя и систему. Обеспечивает обмен данными между пользователем и системой. Использует модель и представление для реализации необходимого действия.
Пользователь использует контроллер, который управляет моделью, которая обновляет представление, которое визуализирует данные для пользователя. Круг замкнулся :).
Хватит теории, перейдем к делу!
Вспомним нашу первую программу.
В ней мы все части уместили в одном файле.
Давайте разделим и реализуем архитектурный паттерн MVC (Model, View, Controller) в SapUI5!
Создадим 3 файла:
index.html:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="UTF-8"/>
<title>sap.hello</title>
<script id="sap-ui-bootstrap"
src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.m"
data-sap-ui-theme="sap_belize"
data-sap-ui-compatVersion="edge"
data-sap-ui-resourceroots='{"sap.hello": ""}'>
</script>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<script>
var oView = sap.ui.view({
id: "idMain",
viewName: "sap.hello.view.main",
type: sap.ui.core.mvc.ViewType.XML
});
oView.placeAt("content");
</script>
</head>
<body class="sapUiBody" id="content">
</body>
</html>
/controller/main.controller.js:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/Device",
"sap/hello/lib/MessageManager"
], function(Controller, Device, MessageManager) {
"use strict";
return Controller.extend("sap.hello.controller.main", {
onInit: function() {
this.getView().addStyleClass(
Device.support.touch ? "sapUiSizeCozy" : "sapUiSizeCompact");
},
onPressBtn: function () {
MessageManager.reportSuccess("привет sap!", "приветствие");
},
onPressBtn_2: function () {
sap.ui.require(["sap/hello/lib/MessageManager"], function(MessageManager_2) {
MessageManager_2.reportSuccess("привет мир", "заголовок");
});
}
});
});
/view/main.view.xml:
<mvc:view controllerName="sap.hello.controller.main" xmlns:html="http://www.w3.org/1999/xhtml" displayBlock="true" xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">
<label text="text" class="sapUiSmallMargin"></label>
<button text="click me" icon="sap-icon://accept" type="Emphasized" press="onPressBtn"></button>
<button text="click me 2" icon="sap-icon://chalkboard" type="Emphasized" press="onPressBtn_2"></button>
</mvc:view>
Так же создадим папку lib и в ней два файла, о назначении которых мы поговорим позже:
/lib/Formatter.js:
sap.ui.define([], function(){
return {
capitalizeFirstLetter: function(sValue) {
return sValue.charAt(0).toUpperCase() + sValue.slice(1);
}
};
});
/lib/MessageManager.js:
sap.ui.define (["sap/m/MessageBox","sap/hello/lib/Formatter"], function(MessageBox, Formatter){
return{
reportSuccess: function(sMsg, sTitle){
MessageBox.show(Formatter.capitalizeFirstLetter(sMsg), {
title: Formatter.capitalizeFirstLetter(sTitle)
});
}
};
});
Попробуем запустить:
Разберем пример более подробно!
В index.html загружаем sapui5.
Видим новую опцию при загрузки sapui5:
data-sap-ui-resourceroots='{"sap.hello": ""}'
Этой записью мы сообщаем ядру SapUI5, что ресурсы в пространстве имен «sap.hello» находятся в той же папке, что и index.html.
Что такое «пространство имен в SapUI5»?
Пространство имен в SapUI5 — это своеобразный ярлык (ссылка) на папку.
Например, если мы напишем:
data-sap-ui-resourceroots='{"sap.test2": "./work"}'
мы обозначим, что ресурсы в пространстве имен sap.test2 находятся в корневой папке work.
Там же появляется новая конструкция:
<script>
var oView = sap.ui.view({
id: "idMain",
viewName: "sap.hello.view.main",
type: sap.ui.core.mvc.ViewType.XML
});
oView.placeAt("content");
</script>
Мы сообщаем SapUI5, что наше представление (View) имеет название sap.hello.view.main (sap.hello — пространство имен, которое ссылается на корень. view.main — папка view, файл main.view).
Тип представления — sap.ui.core.mvc.ViewType.XML. То есть SapUI5 будет искать файл view/main.view.xml.
В SapUI5 можно задавать представления не только в виде JavaScript (как мы познакомились в первом уроке), но и в XML, JSON, HTML.
Перейдем к представлению view/main.view.xml.
<mvc:view controllerName="sap.hello.controller.main" xmlns:html="http://www.w3.org/1999/xhtml" displayBlock="true" xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">
Мы говорим, что у данного представления будет контроллер sap.hello.controller.main (который в пространстве имен sap.hello и находиться в папке {пространство имен}/controller/main.controller.js).
xmlns=»sap.m» означает, что элементы, которые мы используем в представлении, а в данном примере button и label, мы будем брать из библиотеки sap.m.
И вводим «ссылку на библиотеку» mvc=»sap.ui.core.mvc».
Говоря другими словами, исходная запись должна выглядеть следующим образом:
<sap.ui.core.mvc.view controllerName="sap.hello.controller.main"…
но мы решили сократить запись и ввели «ссылку mvc«: mvc=»sap.ui.core.mvc»:
<mvc:view controllerName="sap.hello.controller.main"…
Далее объявили label с предопределенным классом sapUiSmallMargin.
И два Button с иконками и событиями press (нажатие на кнопку).
Оба элемента мы брали из библиотеки sap.m (помните атрибут xmlns=»sap.m»).
Если есть необходимость обратиться к элементам из другой библиотеки. Например, к table из библиотеки sap.ui.table, то либо делаем xmlns:t=»sap.ui.table» и в представлении обращаемся как t:Table, либо обращаемся к полному имени sap.ui.table.Table.
Перейдем к контроллеру controller/main.controller.js.
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/Device",
"sap/hello/lib/MessageManager"
], function(Controller, Device, MessageManager) {
"use strict";
При помощи sap.ui.define (jQuery.sap.declare — синхронная загрузка) мы определяем сам контроллер. Cообщаем ему, какие модули мы планируем асинхронно загрузить и использовать:
- sap/ui/core/mvc/Controller -> Controller
- sap/ui/Device -> Device
- sap/hello/lib/MessageManager -> MessageManager (самописный модуль, файл lib/MessageManager.js в пространстве имен sap/hello)
Функция обратного вызова (Callback):
function(Controller, Device, MessageManager)
сработает сразу после успешной загрузки перечисленных модулей.
Чтобы перевести код в режим полного соответствия современному стандарту, нужно указать специальную директиву use strict (подробней про use strict — https://learn.javascript.ru/strict-mode).
Объявили три функции:
onInit: function() {
this.getView().addStyleClass(
Device.support.touch ? "sapUiSizeCozy" : "sapUiSizeCompact");
},
onPressBtn: function () {
MessageManager.reportSuccess("привет sap!", "приветствие");
},
onPressBtn_2: function () {
sap.ui.require(["sap/hello/lib/MessageManager"], function(MessageManager_2) {
MessageManager_2.reportSuccess("привет мир", "заголовок");
});
}
- onInit — содержимое отработает при инициализации.
- onPressBtn — нажатие на первую кнопку.
- onPressBtn_2 — нажатие на вторую кнопку, в котором вызываем sap.ui.require (подгружаем модуль lib/MessageManager.js пространства имен sap/hello)
Кнопки с событиями onPressBtn и onPressBtn_2 делают одно и то же: Вызывают метод reportSuccess, который описан в sap/hello/lib/MessageManager.
Только для onPressBtn мы описали модуль MessageManager глобально. В onPressBtn_2 описали модуль локально, внутри события.
Посмотрим что делает lib/MessageManager.js.
sap.ui.define (["sap/m/MessageBox","sap/hello/lib/Formatter"], function(MessageBox, Formatter){
Определяем модуль и асинхронно загружаем стандартную sap/m/MessageBox и еще один самописный модуль sap/hello/lib/Formatter.
После загрузки содержимое функции
function(MessageBox, Formatter){
отработает.
Описали метод reportSuccess:
reportSuccess: function(sMsg, sTitle){
MessageBox.show(Formatter.capitalizeFirstLetter(sMsg), {
title: Formatter.capitalizeFirstLetter(sTitle)
});
});
который вызывает сообщение MessageBox.show и в качестве параметров передает возвращаемое значение Formatter.capitalizeFirstLetter: sMsg и Formatter.capitalizeFirstLetter: title.
Formatter.capitalizeFirstLetter (модуль Formatter.js) берет строку (sValue), первую (элемент №0 в строке) букву (sValue.charAt(0)) поднимает в верхний регистр (toUpperCase()), прибавляет к строке без первой буквы (sValue.slice(1)) и возвращает результат:
capitalizeFirstLetter: function(sValue) {
return sValue.charAt(0).toUpperCase() + sValue.slice(1);
}
Отдельно отметим, что модуль Formatter.js начинается с пустого:
sap.ui.define([], function(){
В итоге
1. Мы разделили приложение на 2 части:
- Вынесли отдельно часть, отвечающую за отображение информации на экране — Представление (view) /view/main.view.xml
- Вынесли отдельно часть, отвечающую за обработку действий пользователя — Контроллер (controller) /controller/main.controller.js
2. Реализовали модульность.
Вынесли в отдельный модуль (файл MessageManager.js) функцию показа сообщения при нажатии на кнопку и вынесли в отдельный модуль (файл Formatter.js) функцию обработки строки (первая буква в строке — заглавная).
Исходники к уроку №2 можно скачать по ссылке https://github.com/kannade/modularization_sapui5.
Очень интересный Блог, спасибо. Продолжайте писать и всего наилучшего !
интересно написано , буду дальше читать …
Сервер запускаю с помощью https://www.npmjs.com/package/serve но получаю ошибку ui5loader-dbg.js:1279 GET https://sapui5.hana.ondemand.com/resources/sap/m/label.js 404
и
Access to XMLHttpRequest at ‘https://sapui5.hana.ondemand.com/resources/sap/m/label.js’ from origin ‘http://localhost:5000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.