You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/uk/7-bank-project/1-template-route/README.md

22 KiB

Створення банківського додатку Частина 1: HTML-шаблони та маршрути у веб-додатку

Передлекційний тест

Передлекційний тест

Вступ

З появою JavaScript у браузерах вебсайти стали більш інтерактивними та складними, ніж будь-коли. Вебтехнології тепер часто використовуються для створення повнофункціональних додатків, які працюють безпосередньо у браузері, і які ми називаємо веб-додатками. Оскільки веб-додатки є дуже інтерактивними, користувачі не хочуть чекати повного перезавантаження сторінки щоразу, коли виконується якась дія. Саме тому JavaScript використовується для оновлення HTML безпосередньо через DOM, щоб забезпечити більш плавний користувацький досвід.

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

Передумови

Вам потрібен локальний вебсервер для тестування веб-додатку, який ми створимо в цьому уроці. Якщо у вас його немає, ви можете встановити Node.js і скористатися командою npx lite-server у папці вашого проєкту. Це створить локальний вебсервер і відкриє ваш додаток у браузері.

Підготовка

На вашому комп'ютері створіть папку з назвою bank і файл index.html всередині неї. Ми почнемо з цього шаблону HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bank App</title>
  </head>
  <body>
    <!-- This is where you'll work -->
  </body>
</html>

HTML-шаблони

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

  • Потрібно перезавантажувати весь HTML при перемиканні екранів, що може бути повільним.
  • Важко ділитися даними між різними екранами.

Інший підхід полягає у використанні лише одного HTML-файлу та визначенні кількох HTML-шаблонів за допомогою елемента <template>. Шаблон — це багаторазовий HTML-блок, який не відображається браузером і має бути створений під час виконання за допомогою JavaScript.

Завдання

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

<div id="app">Loading...</div>

Ми надаємо йому id, щоб пізніше було легше знайти його за допомогою JavaScript.

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

Далі додамо нижче HTML-шаблон для сторінки входу. Поки що ми додамо лише заголовок і секцію з посиланням, яке ми будемо використовувати для навігації.

<template id="login">
  <h1>Bank App</h1>
  <section>
    <a href="/dashboard">Login</a>
  </section>
</template>

Потім додамо ще один HTML-шаблон для сторінки панелі керування. Ця сторінка міститиме різні секції:

  • Заголовок із назвою та посиланням для виходу
  • Поточний баланс банківського рахунку
  • Список транзакцій, відображений у таблиці
<template id="dashboard">
  <header>
    <h1>Bank App</h1>
    <a href="/login">Logout</a>
  </header>
  <section>
    Balance: 100$
  </section>
  <section>
    <h2>Transactions</h2>
    <table>
      <thead>
        <tr>
          <th>Date</th>
          <th>Object</th>
          <th>Amount</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </section>
</template>

Порада: під час створення HTML-шаблонів, якщо ви хочете побачити, як вони виглядатимуть, ви можете закоментувати рядки <template> і </template>, обгорнувши їх у <!-- -->.

Чому, на вашу думку, ми використовуємо атрибути id у шаблонах? Чи могли б ми використати щось інше, наприклад класи?

Відображення шаблонів за допомогою JavaScript

Якщо ви спробуєте відкрити поточний HTML-файл у браузері, ви побачите, що він застряг на екрані з написом Loading.... Це тому, що нам потрібно додати трохи JavaScript-коду, щоб створити та відобразити HTML-шаблони.

Створення шаблону зазвичай виконується у 3 кроки:

  1. Знайти елемент шаблону в DOM, наприклад, використовуючи document.getElementById.
  2. Клонувати елемент шаблону за допомогою cloneNode.
  3. Прикріпити його до DOM під видимим елементом, наприклад, використовуючи appendChild.

Чому нам потрібно клонувати шаблон перед тим, як прикріпити його до DOM? Що, на вашу думку, станеться, якщо пропустити цей крок?

Завдання

Створіть новий файл із назвою app.js у папці вашого проєкту та імпортуйте цей файл у секцію <head> вашого HTML:

<script src="app.js" defer></script>

Тепер у app.js ми створимо нову функцію updateRoute:

function updateRoute(templateId) {
  const template = document.getElementById(templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

Те, що ми робимо тут, — це саме ті 3 кроки, описані вище. Ми створюємо шаблон із id templateId і вставляємо його клонований вміст у наш елемент-заповнювач додатку. Зверніть увагу, що нам потрібно використовувати cloneNode(true), щоб скопіювати весь піддерево шаблону.

Тепер викличте цю функцію з одним із шаблонів і подивіться на результат.

updateRoute('login');

Яка мета цього коду app.innerHTML = '';? Що станеться без нього?

Створення маршрутів

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

mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html

Якщо ви створите вебсервер із коренем mywebsite, відображення URL буде таким:

https://site.com            --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/     --> mywebsite/admin/index.html

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

Завдання

Ми використаємо простий об'єкт для реалізації карти між шляхами URL і нашими шаблонами. Додайте цей об'єкт на початку вашого файлу app.js.

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard' },
};

Тепер трохи змінимо функцію updateRoute. Замість того, щоб передавати безпосередньо templateId як аргумент, ми хочемо спочатку отримати поточний URL, а потім використати нашу карту, щоб отримати відповідне значення templateId. Ми можемо використовувати window.location.pathname, щоб отримати лише частину шляху з URL.

function updateRoute() {
  const path = window.location.pathname;
  const route = routes[path];

  const template = document.getElementById(route.templateId);
  const view = template.content.cloneNode(true);
  const app = document.getElementById('app');
  app.innerHTML = '';
  app.appendChild(view);
}

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

Що станеться, якщо ви введете невідомий шлях у URL? Як ми могли б вирішити цю проблему?

Додавання навігації

Наступний крок для нашого додатку — додати можливість переходу між сторінками без необхідності змінювати URL вручну. Це передбачає дві речі:

  1. Оновлення поточного URL
  2. Оновлення відображуваного шаблону на основі нового URL

Ми вже подбали про другу частину за допомогою функції updateRoute, тому нам потрібно зрозуміти, як оновити поточний URL.

Ми скористаємося JavaScript, а точніше history.pushState, який дозволяє оновлювати URL і створювати новий запис в історії переглядів без перезавантаження HTML.

Примітка: Хоча HTML-елемент прив'язки <a href> можна використовувати самостійно для створення гіперпосилань на різні URL, за замовчуванням він змусить браузер перезавантажити HTML. Необхідно запобігти цій поведінці під час обробки маршрутизації за допомогою власного JavaScript, використовуючи функцію preventDefault() для події кліку.

Завдання

Давайте створимо нову функцію, яку ми зможемо використовувати для навігації в нашому додатку:

function navigate(path) {
  window.history.pushState({}, path, path);
  updateRoute();
}

Цей метод спочатку оновлює поточний URL на основі заданого шляху, а потім оновлює шаблон. Властивість window.location.origin повертає корінь URL, що дозволяє нам реконструювати повний URL із заданого шляху.

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

function updateRoute() {
  const path = window.location.pathname;
  const route = routes[path];

  if (!route) {
    return navigate('/login');
  }

  ...

Якщо маршрут не може бути знайдений, ми тепер перенаправимо на сторінку login.

Тепер створимо функцію для отримання URL при кліку на посилання та запобігання стандартній поведінці браузера для посилань:

function onLinkClick(event) {
  event.preventDefault();
  navigate(event.target.href);
}

Давайте завершимо систему навігації, додавши прив'язки до наших посилань Login і Logout у HTML.

<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>

Об'єкт event вище захоплює подію click і передає її до нашої функції onLinkClick.

Використовуючи атрибут onclick, прив'яжіть подію click до JavaScript-коду, тут виклику функції navigate().

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

Метод history.pushState є частиною стандарту HTML5 і реалізований у всіх сучасних браузерах. Якщо ви створюєте веб-додаток для старих браузерів, є трюк, який можна використовувати замість цього API: використання хешу (#) перед шляхом дозволяє реалізувати маршрутизацію, яка працює з регулярною навігацією за допомогою прив'язок і не перезавантажує сторінку, оскільки її метою було створення внутрішніх посилань на сторінці.

Обробка кнопок "Назад" і "Вперед" у браузері

Використання history.pushState створює нові записи в історії навігації браузера. Ви можете перевірити це, утримуючи кнопку назад у вашому браузері, це має виглядати приблизно так:

Знімок екрана історії навігації

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

Це тому, що додаток не знає, що нам потрібно викликати updateRoute() щоразу, коли історія змінюється. Якщо ви подивитеся на документацію history.pushState, ви побачите, що якщо стан змінюється — тобто ми перейшли на інший URL — подія popstate викликається. Ми використаємо це, щоб виправити цю проблему.

Завдання

Щоб переконатися, що відображуваний шаблон оновлюється, коли історія браузера змінюється, ми прив'яжемо нову функцію, яка викликає updateRoute(). Ми зробимо це внизу нашого файлу app.js:

window.onpopstate = () => updateRoute();
updateRoute();

Примітка: ми використали стрілкову функцію для оголошення нашого обробника події popstate для стислості, але звичайна функція працювала б так само.

Ось відео-нагадування про стрілкові функції:

Стрілкові функції

🎥 Натисніть на зображення вище, щоб переглянути відео про стрілкові функції.

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


🚀 Виклик

Додайте новий шаблон і маршрут для третьої сторінки, яка показує авторів цього додатку.

Післялекційний тест

Післялекційний тест

Огляд і самостійне навчання

Маршрутизація є однією з несподівано складних частин веброзробки, особливо коли веб переходить від поведінки з оновленням сторінок до оновлень у рамках односторінкових додатків. Прочитайте трохи про те, як служба Azure Static Web App обробляє маршрутизацію. Чи можете ви пояснити, чому деякі з описаних у цьому документі рішень є необхідними?

Завдання

Покращіть маршрутизацію


Відмова від відповідальності:
Цей документ був перекладений за допомогою сервісу автоматичного перекладу Co-op Translator. Хоча ми прагнемо до точності, будь ласка, майте на увазі, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ на його рідній мові слід вважати авторитетним джерелом. Для критичної інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникають внаслідок використання цього перекладу.