0 follower

Представлення

Представлення є частиною архітектури MVC. Це код, який відповідає за відображення даних кінцевим користувачам. У веб-додатку представлення зазвичай створені у вигляді шаблонів представлень, які є файлами скриптів PHP, що містять переважно HTML-код та презентаційний PHP-код. Управління ними здійснюється за допомогою компонента додатку view, який надає часто використовувані методи для полегшення компонування та формування представлення. Для простоти, часто шаблони представлень або файли шаблонів представлень називаються представленнями.

Створення представлень

Як зазначено вище, представлення є простим скриптом PHP, який містить HTML- та PHP-код. Далі наведено представлення, що представляє форму входу користувача. Як можна побачити, PHP-код використовується для генерування динамічного вмісту, такого як заголовку сторінки та форми, тоді як HTML-код організовує їх у презентабельну HTML-сторінку.

<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;

/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $model app\models\LoginForm */

$this->title = 'Вхід';
?>
<h1><?= Html::encode($this->title) ?></h1>

<p>Будьдьь<?php $form = ActiveForm::begin(); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <?= Html::submitButton('Увійти') ?>
<?php ActiveForm::end(); ?>

Всередині представлення ви можете використовувати $this, що відноситься до компоненту представлення, який забезпечує керування цим шаблоном та його формування.

Окрім $this, у представленні можуть бути інші попередньо визначені змінні, такі як $model у прикладі вище. Ці змінні представляють дані, які були передані у представлення через контролери або інші об’єкти, які спричинили формування представлення.

Підказка: Попередньо визначені змінні перелічені в блоці коментаря у початку представлення, так що вони можуть бути розпізнані в інтегрованих середовищах розробки (IDE). Це також є хорошим способом документування ваших представлень.

Безпека

При створенні представлень, які генерують HTML-сторінки, важливо кодувати і/або фільтрувати дані, що надходять від кінцевих користувачів, перед їх відображенням. В протилежному випадку ваш додаток може стати предметом атак типу міжсайтовий скриптінг (XSS).

Для відображення звичайного тексту спершу закодуйте його за допомогою yii\helpers\Html::encode(). Наприклад, в наступному коді перед відображенням кодується ім’я користувача:

<?php
use yii\helpers\Html;
?>

<div class="username">
    <?= Html::encode($user->name) ?>
</div>

Для відображення HTML-вмісту використовуйте yii\helpers\HtmlPurifier, щоб відфільтрувати потенційно небезпечний вміст. Наприклад, в наступному коді фільтрується вміст публікації перед відображенням:

<?php
use yii\helpers\HtmlPurifier;
?>

<div class="post">
    <?= HtmlPurifier::process($post->text) ?>
</div>

Підказка: В той час як HTMLPurifier бездоганно виконує роботу, щоб зробити вивід безпечним, він не є швидким. Вам потрібно розглянути можливість кешування результатів фільтрування, якщо ваш додаток потребує високої швидкодії.

Впорядкування представлень

Подібно до контролерів та моделей, існують домовленості щодо впорядкування представлень.

  • Представлення, які формуються контролером, повинні бути розміщені в директорії @app/views/ControllerID за замовчуванням, де ControllerID відповідає ідентифікатору контролера. Наприклад, для класу контролера PostController директорія повинна бути @app/views/post; для класу PostCommentController директорія повинна бути @app/views/post-comment. У випадку, коли контролер належить модулю, директорія повинна бути views/ControllerID у директорії модуля.
  • Представлення, які формуються у віджетах, повинні бути розміщені в директорії WidgetPath/views за замовчуванням, де WidgetPath означає шлях до директорії, в якій знаходиться файл класу віджету.
  • Для представлень, які формуються іншими об’єктами, рекомендується виконувати домовленості подібно до віджетів.

Ви можете налаштувати ці типові директорії представлень, перевизначивши метод yii\base\ViewContextInterface::getViewPath() контролерів або віджетів.

Формування представлень

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

/**
 * @param string $view ім’я представлення або шлях до файлу, в залежності від того, який метод формування використовується
 * @param array $params дані, які передаються представленню
 * @return string результат формування
 */
methodName($view, $params = [])

Формування в контролерах

Всередині контролерів, ви можете викликати наступні методи контролера для формування представлень:

Наприклад:

namespace app\controllers;

use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

class PostController extends Controller
{
    public function actionView($id)
    {
        $model = Post::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException;
        }

        // формує представлення з ім’ям "view" та застосовує макет до нього
        return $this->render('view', [
            'model' => $model,
        ]);
    }
}

Формування у віджетах

Всередині віджетів, ви можете викликати наступні методи віджету для формування представлень.

Наприклад:

namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class ListWidget extends Widget
{
    public $items = [];

    public function run()
    {
        // формує представлення з ім’ям "list"
        return $this->render('list', [
            'items' => $this->items,
        ]);
    }
}

Формування у представленнях

Ви можете формувати представлення всередині іншого представлення за допомогою виклику одного з наступних методів наданих компонентом представлення:

Наприклад, наступний код у представленні формує файл представлення _overview.php, який знаходиться в тій самій директорії, що й представлення, яке зараз формується. Запам’ятайте, що $this у представленні відноситься до компонента представлення:

<?= $this->render('_overview') ?>

Формування в інших місцях

В будь-якому місці ви можете отримати доступ до компонента додатка представлення за допомогою виразу Yii::$app->view та потім викликати його вищезгадані методи для формування представлення. Наприклад:

// відображає файл представлення "@app/views/site/license.php"
echo \Yii::$app->view->renderFile('@app/views/site/license.php');

Іменовані представлення

При формуванні представлення ви можете визначити його, використовуючи ім’я представлення або шлях/псевдонім до файлу представлення. У більшості випадків ви будете використовувати перший варіант, тому що він більш лаконічний та гнучкий. Представлення, визначені за допомогою імен називаються іменованими представленнями.

Ім’я представлення перетворюється у відповідний шлях до файлу представлення за наступними правилами:

  • Ім’я представлення можна вказувати без розширення імені файлу. У цьому випадку в якості розширення буде використовуватись .php. Наприклад, ім’я представлення about відповідає імені файлу about.php.
  • Якщо ім’я представлення починається з двох слешів //, то відповідним шляхом до файлу представлення буде @app/views/ViewName. Це означає, що представлення шукається в директорії представлень додатку. Наприклад, //site/about буде перетворено в @app/views/site/about.php.
  • Якщо ім’я представлення починається з одного слешу /, то шлях до файлу представлення складатиметься з імені представлення та префіксу у вигляді директорії представлень поточного активного модулю. Якщо немає активного модулю, то буде використовуватись @app/views/ViewName. Наприклад, /user/create буде перетворено в @app/modules/user/views/user/create.php, якщо поточним активним модулем є user. Якщо немає активного модулю, то шляхом до файлу представлення буде @app/views/user/create.php.
  • Якщо представлення формується з контекстом і контекст має реалізований інтерфейс yii\base\ViewContextInterface, то шлях до файлу представлення складатиметься з префікса у вигляді директорії представлень контексту та з імені представлення. Це частіше застосовується до представлень, які формуються всередині контролерів або віджетів. Наприклад, about буде перетворено в @app/views/site/about.php, якщо контекстом є контролер SiteController.
  • Якщо представлення формується в середині іншого представлення, директорія, що містить інше представлення буде додана перед іменем представлення, що формується, для створення актуального шляху до файлу. Наприклад, item перетвориться в @app/views/post/item.php, якщо буде формуватись із представлення @app/views/post/index.php.

Згідно з наведеними правилами, виклик $this->render('view') у контролері app\controllers\PostController буде формувати представлення з файлу @app/views/post/view.php, в той час як виклик $this->render('_overview') у тому представленні буде формувати представлення з файлу @app/views/post/_overview.php.

Доступ до даних у представленнях

Є два підходи при доступові до даних в середині представлення: "вштовхування" та "витягування".

Передаючи дані другим параметром у методи формування представлення, ви використовуєте підхід "вштовхування". Дані повинні бути надані у вигляді масиву пар ключ-значення. Під час формування представлення буде викликана функція PHP extract() на цьому масиві, видобувши таким чином змінні у представлення. Наприклад, наступний код формування представлення у контролері "вштовхне" дві змінні до представлення report: $foo = 1 та $bar = 2.

echo $this->render('report', [
    'foo' => 1,
    'bar' => 2,
]);

Підхід "витягування" активно здобуває дані з компоненту представлення або інших об’єктів, доступних у представленнях (наприклад, Yii::$app). Використовуючи нижче наведений код як приклад, всередині представлення можна отримати об’єкт за допомогою виразу $this->context. У результаті, стає можливим доступ до усіх властивостей та методів контролера у представленні report, як, наприклад, ідентифікатору контролера, що наведений у прикладі:

Ідентифікатор<?= $this->context->id ?>

Підхід "вштовхування" є бажанішим шляхом для доступу до даних у представленнях, тому що він робить представлення менш залежними від об’єктів контексту, але його недоліком є необхідність весь час будувати масив даних вручну, що може стати стомливим та збільшує вірогідність допустити помилку, якщо представлення використовується та формується у різних місцях.

Обмін даними між представленнями

Компонент представлення надає властивість params, яку можна використовувати для обміну даними між представленнями.

Наприклад, в представленні about, ви можете мати наступний код, який визначає поточну частину "хлібних крихт".

$this->params['breadcrumbs'][] = 'Про нас';

Потім у файлі макету, який також є представленням, ви можете відобразити "хлібні крихти", використовуючи дані передані через params:

<?= yii\widgets\Breadcrumbs::widget([
    'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>

Макети

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

Створення макетів

Оскільки макети є представленнями, вони можуть бути створенні тим самим шляхом, як і звичайні представлення. За замовчуванням, макети зберігаються в директорії @app/views/layouts. Макети, які використовуються у модулі, повинні зберігатись в директорії views/layouts під директорією модуля. Ви можете налаштувати типову директорію для макетів сконфігурувавши властивість yii\base\Module::$layoutPath додатку або модулів.

Наступний приклад показує як виглядає макет. Майте на увазі, що для кращого сприйняття код у макеті дуже спрощений. На практиці, ви можливо захочете додати більше вмісту до нього, такого як теги секції <head>, головне меню та інше.

<?php
use yii\helpers\Html;

/* @var $this yii\web\View */
/* @var $content string */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <?= Html::csrfMetaTags() ?>
    <title><?= Html::encode($this->title) ?></title>
    <?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
    <header>Моя<?= $content ?>
    <footer>Моя2014</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

Як ви можете бачити, макет генерує HTML-теги, які є спільними для всіх сторінок. У секції <body> макет виводить змінну $content, яка містить результат формування вкладених представлень та "вштовхується" у макет під час виклику методу yii\base\Controller::render().

В більшості макетів наступні методи будуть викликатись як показано у вищенаведеному коді. Ці методи здебільшого породжують події, пов’язані з процесом формування, щоб скрипти та теги, які зареєстровані в інших місцях могли бути правильно включенні в місцях, де ці методи викликаються.

  • beginPage(): Цей метод повинен викликатись на самому початку макету. Він породжує подію EVENT_BEGIN_PAGE, яка слугує ознакою початку сторінки.
  • endPage(): Цей метод повинен викликатись в кінці макету. Він породжує подію EVENT_END_PAGE, яка слугує ознакою кінця сторінки.
  • head(): Цей метод повинен викликатись всередині секції <head> HTML-сторінки. Він генерує заповнювач, який буде замінено зареєстрованим HTML-кодом (наприклад, теги link і meta), коли сторінка буде повністю сформована.
  • beginBody(): Цей метод повинен викликатись на початку секції <body>. Він породжує подію EVENT_BEGIN_BODY та генерує заповнювач, який буде замінено зареєстрованим HTML-кодом (наприклад, JavaScript) на початку секції <body>.
  • endBody(): Цей метод повинен викликатись у кінці секції <body>. Він породжує подію EVENT_END_BODY та генерує заповнювач, який буде замінено зареєстрованим HTML-кодом (наприклад, JavaScript) у кінці секції <body>.

Доступ до даних у макетах

Всередині макету ви маєте доступ до двох попередньо визначених змінних: $this та $content. Перша посилається на компонент представлення, як і у звичайних представленнях, в той час як друга містить результат формування вкладеного представлення, який формується викликом методу render() у контролерах.

Якщо ви бажаєте мати доступ до інших даних у макетах, то вам потрібно використовувати підхід "витягування", описаний в підрозділі Доступ до даних у представленнях. Якщо ви бажаєте отримати дані з вкладеного представлення у макеті, то можете використати підхід описаний у підрозділі Обмін даними між представленнями.

Використання макетів

Як описано в підрозділі Формування в контролерах, під час формування представлення через виклик методу render() у контролері, буде застосовний макет до результату формування. За замовчуванням, буде використовуватись макет @app/views/layouts/main.php.

Ви можете використовувати інший макет сконфігурувавши властивість yii\base\Application::$layout або yii\base\Controller::$layout. Перша відповідає за макет, який використовується усіма контролерами, друга ж перекриває першу для окремих контролерів. Наприклад, наступний код налаштовує контролер post на використання макету @app/views/layouts/post.php під час формування його представлень. Інші контролери, за умови, що їх властивість layout не встановлена, будуть надалі використовувати типовий макет @app/views/layouts/main.php.

namespace app\controllers;

use yii\web\Controller;

class PostController extends Controller
{
    public $layout = 'post';
    
    // ...
}

Для контролерів, що належать модулю, ви можете також сконфігурувати властивість модуля layout, щоб використовувати окремий макет для цих контролерів.

Оскільки властивість layout може бути сконфігурована на різних рівнях (контролери, моделі, додаток), "за лаштунками" Yii виконує два кроки, щоб визначити, який файл макету є актуальним для окремого контролера.

На першому кроці, визначається значення layout та контекстний модуль:

  • Якщо властивість контролера yii\base\Controller::$layout відмінна від null, використовується вона і модуль контролера як контекстний модуль.
  • Якщо layout не визначено (дорівнює null), здійснюється пошук у всіх батьківських модулях (включаючи сам додаток) контролера та знаходиться перший модуль, властивість layout якого не дорівнює null. Використовується значення цього модуля layout та сам модуль як контекстний модуль. Якщо такого модуля не знайдено, це означає, що макет не буде застосовано.

На другому кроці, визначається актуальний файл макету відповідно до значення layout та контекстного модулю, визначених на першому кроці. Значенням layout може бути:

  • псевдонім шляху (наприклад, @app/views/layouts/main);
  • абсолютний шлях (наприклад, /main): значення layout починається зі слешу. Актуальний файл макету буде шукатись під директорією макетів додатка, яка типово дорівнює @app/views/layouts;
  • відносний шлях (наприклад, main): актуальний файл макету буде шукатись під директорією макетів контекстного модуля, яка типово є директорією views/layouts під директорією модуля;
  • логічне значення false: макет не буде застосовано.

Якщо значення layout не містить розширення файлу, то буде використане типове розширення .php.

Вкладені макети

Іноді потрібно вкласти один макет в інший. Наприклад, у різних розділах веб-сайту ви захочете використовувати різні макети, які мають однаковий базовий макет, що генерує загальну структуру HTML5-сторінки. Це можна зробити за допомогою викликів beginContent() та endContent() в дочірніх макетах як наведено нижче:

<?php $this->beginContent('@app/views/layouts/base.php'); ?>

...вміст<?php $this->endContent(); ?>

Як показано вище, вміст дочірнього макету повинен бути замкнений між beginContent() та endContent(). Параметр, який передається в beginContent() визначає батьківський макет. Цей може бути файл макету чи псевдонім шляху.

Використовуючи цей підхід, можна вкладати макети більше, ніж на один рівень.

Використання блоків

Блоки дозволяють визначати вміст представлення в одному місці, а відображати в іншому. Вони часто використовуються разом з макетами. Наприклад, ви можете визначити блок у вкладеному представленні та відобразити його у макеті.

Виклики beginBlock() та endBlock() визначають блок. Потім блок може бути доступним через $view->blocks[$blockID], де $blockID означає унікальний ідентифікатор, який ви призначаєте блоку під час його визначення.

Нижченаведений приклад показує як ви можете використовувати блоки у вкладеному представленні для налаштовування окремих частин макету.

Спершу, у вкладеному представленні, визначається один чи більше блоків:

...

<?php $this->beginBlock('block1'); ?>

...вміст1...

<?php $this->endBlock(); ?>

...

<?php $this->beginBlock('block3'); ?>

...вміст3...

<?php $this->endBlock(); ?>

Потім, у макеті, формуються блоки, якщо вони присутні, або відображається деякий типовий вміст, якщо блок не визначено.

...
<?php if (isset($this->blocks['block1'])): ?>
    <?= $this->blocks['block1'] ?>
<?php else: ?>
    ... типовий1 ...
<?php endif; ?>

...

<?php if (isset($this->blocks['block2'])): ?>
    <?= $this->blocks['block2'] ?>
<?php else: ?>
    ... типовий2 ...
<?php endif; ?>

...

<?php if (isset($this->blocks['block3'])): ?>
    <?= $this->blocks['block3'] ?>
<?php else: ?>
    ... типовий3 ...
<?php endif; ?>
...

Використання компонентів представлення

Компоненти представлення надають багато можливостей, пов’язаних із представленням. Ви можете отримувати компоненти представлення за допомогою створення індивідуальних екземплярів yii\base\View або його дочірніх класів, але у більшості випадків ви переважно будете використовувати компонент view додатку. Ви можете сконфігурувати цей компонент у конфігураціях додатку як наведено нижче:

[
    // ...
    'components' => [
        'view' => [
            'class' => 'app\components\View',
        ],
        // ...
    ],
]

Компоненти представлення надають наступні корисні можливості, пов’язані з представленням, які описані більш детально в окремих розділах:

Ви також можете часто використовувати наступні другорядні, але корисні, можливості в процесі розробки веб-сторінок.

Встановлення заголовків сторінок

Кожна веб-сторінка повинна мати заголовок. Звичайно тег заголовку виводиться в макеті. Однак, на практиці заголовок часто визначається у вкладених представленнях, а не в макетах. Для вирішення цієї проблеми, компонент yii\web\View надає властивість title, за допомогою якої можна передавати з вкладеного представлення до макетів інформацію заголовку.

Для використання цієї можливості, в кожному вкладеному представленні ви можете задати заголовок як наведено нижче:

<?php
$this->title = 'Мій заголовок сторінки';
?>

Потім переконайтесь, що маєте наступний код в секції <head> у макеті:

<title><?= Html::encode($this->title) ?></title>

Реєстрація мета-тегів

Для веб-сторінок зазвичай потрібно генерувати різноманітні мета-теги, які мають різне цільове призначення. Подібно до заголовків сторінок, мета-теги фігурують в секції <head> та зазвичай генеруються в макетах.

Якщо ви бажаєте визначити, які мета-теги генерувати у вкладених представленнях, ви можете викликати yii\web\View::registerMetaTag() у вкладеному представленні, подібно до наведеного:

<?php
$this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework, php']);
?>

В коді вище реєструється мета-тег "keywords" у компоненті представлення. Зареєстрований мета-тег формується після закінчення формування макету. Наступний HTML-код буде згенеровано та вставлено в місці, де ви викличете yii\web\View::head() у макеті:

<meta name="keywords" content="yii, framework, php">

Зауважте, якщо викликати yii\web\View::registerMetaTag() декілька разів, в результаті цього зареєструється кілька мета-тегів, не зважаючи на те, чи мета-теги однакові чи ні.

Щоб мати лише один екземпляр специфічного типу мета-тегу, потрібно визначати ключ в другому параметрі під час виклику методу. Наприклад, наступний код реєструє два мета-теги "description". Однак, лише другий буде сформовано.

$this->registerMetaTag(['name' => 'description', 'content' => 'Це мій класний веб-сайт, який створено за допомогою Yii!'], 'description');
$this->registerMetaTag(['name' => 'description', 'content' => 'Цей веб-сайт про смішних єнотів.'], 'description');

Так само як і мета-теги, теги link є корисними у багатьох випадках, як, наприклад, налаштування favicon, посилання на стрічку новин (RSS) або делегування OpenID іншому серверу. Ви можете працювати з тегами link подібним шляхом як і з мета-тегами, використовуючи yii\web\View::registerLinkTag(). Наприклад, у вкладеному представленні, ви можете зареєструвати тег link наступним чином,

$this->registerLinkTag([
    'title' => 'Свіжі новини про Yii',
    'rel' => 'alternate',
    'type' => 'application/rss+xml',
    'href' => 'http://www.yiiframework.com/rss.xml/',
]);

Результатом вищенаведеного коду буде

<link title="Свіжі новини про Yii" rel="alternate" type="application/rss+xml" href="http://www.yiiframework.com/rss.xml/">

Подібно до registerMetaTags(), ви можете визначати ключ під час виклику registerLinkTag() для запобігання генерування повторних тегів link одного типу.

Події у представленнях

Компоненти представлення породжують кілька подій в процесі формування представлення. Ви можете призначити обробники на ці події для вставлення вмісту в представлення або для опрацювання сформованих результатів перед їх відправленням кінцевим користувачам.

Наприклад, наступний код вставить поточну дату в кінці секції <body> сторінки:

\Yii::$app->view->on(View::EVENT_END_BODY, function () {
    echo date('Y-m-d');
});

Формування статичних сторінок

До статичних сторінок відносяться ті веб-сторінки, в яких основний вміст здебільшого статичний та не потребує доступу до динамічних даних, що передаються з контролерів.

Можна виводити статичні сторінки, розмістивши їх код у представленні, а потім використовуючи код подібний до наведеного у контролері:

public function actionAbout()
{
    return $this->render('about');
}

Якщо веб-сайт містить багато статичних сторінок, було б дуже стомливим повторювати схожий код багато разів. Для вирішення цієї проблеми можна впровадити автономну дію yii\web\ViewAction у контролері. Наприклад,

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actions()
    {
        return [
            'page' => [
                'class' => 'yii\web\ViewAction',
            ],
        ];
    }
}

Тепер, якщо створити представлення з ім’ям about у директорії @app/views/site/pages, стане можливим відображення цього представлення за наступною URL-адресою:

http://localhost/index.php?r=site%2Fpage&view=about

Параметр view із запиту GET вказує автономній дії yii\web\ViewAction, яке представлення запитане. Потім дія здійснює пошук цього представлення в директорії @app/views/site/pages. Ви можете сконфігурувати yii\web\ViewAction::$viewPrefix, щоб змінити директорію для пошуку цих представлень.

Кращі практики

Представлення відповідають за репрезентацію моделей у форматі зрозумілому кінцевим користувачам. В цілому, представлення

  • повинні здебільшого містити презентаційний код, такий як HTML та простий PHP-код для подання, форматування та формування даних;
  • не повинні містити код, який виконує запити до БД. Такий код повинен бути в моделях;
  • повинні уникати безпосереднього доступу до даних запиту, таких як $_GET, $_POST. Це обов’язок контролерів. У випадку необхідності дані запиту повинні бути передані в представлення через контролери;
  • можуть читати властивості моделі, але не повинні змінювати їх.

Щоб зробити представлення більш контрольованими, уникайте створення представлень, які є дуже складними або містять забагато надлишкового коду. Використовуйте наступні техніки, щоб досягнути цього:

  • використовуйте макети для відображення спільних презентаційних секцій (наприклад, шапка та футер сторінки);
  • розділяйте складне представлення на декілька менших. Менші представлення можуть бути сформовані та складені у більше за допомогою методів формування описаних раніше у цьому розділі;
  • створюйте та використовуйте віджети як будівельні блоки представлень;
  • створюйте та використовуйте класи-хелпери для перетворення та форматування даних у представленнях.

Found a typo or you think this page needs improvement?
Edit it on github !