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-тег <body> елемент-заповнювач, який ми будемо використовувати для створення різних екранів нашого додатку:

<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 для стислості, але звичайна функція працювала б так само.

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

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

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

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


🚀 Виклик

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

Післялекційна вікторина

Післялекційна вікторина

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

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

Завдання

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


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