Update Translations

This commit is contained in:
Lee Stott
2025-08-23 20:47:28 +01:00
committed by GitHub
parent eff26d962b
commit 4c689557b5
497 changed files with 0 additions and 50930 deletions

View File

@@ -1,288 +0,0 @@
# Plantillas HTML y rutas en una aplicación web
## [Pre-lecture prueba](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41)
### Introducción
Desde la llegada de JavaScript a los navegadores, los sitios web se están volviendo más interactivos y complejos que nunca. Las tecnologías web ahora se utilizan comúnmente para crear aplicaciones completamente funcionales que se ejecutan directamente en un navegador que llamamos [aplicaciones web](https://en.wikipedia.org/wiki/Web_application). Como las aplicaciones web son muy interactivas, los usuarios no quieren esperar a que se vuelva a cargar la página completa cada vez que se realiza una acción. Es por eso que JavaScript se usa para actualizar el HTML directamente usando el DOM, para brindar una experiencia de usuario más fluida.
En esta lección, vamos a sentar las bases para crear una aplicación web bancaria, utilizando plantillas HTML para crear múltiples pantallas que se pueden mostrar y actualizar sin tener que volver a cargar toda la página HTML.
### Requisito previo
Necesita un servidor web local para probar la aplicación web que crearemos en esta lección. Si no tiene uno, puede instalar [Node.js](https://nodejs.org) y usar el comando `npx lite-server` de la carpeta de su proyecto. Creará un servidor web local y abrirá su aplicación en un navegador.
### Preparación
En su computadora, cree una carpeta llamada `bank` con un archivo llamado `index.html` dentro. Comenzaremos desde este HTML [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code):
```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>
<!-- Aquí es donde trabajarás -->
</body>
</html>
```
---
## Plantillas HTML
Si desea crear varias pantallas para una página web, una solución sería crear un archivo HTML para cada pantalla que desee mostrar. Sin embargo, esta solución tiene algunos inconvenientes:
- Tienes que volver a cargar todo el HTML al cambiar de pantalla, lo que puede ser lento.
- Es difícil compartir datos entre las diferentes pantallas.
Otro enfoque es tener un solo archivo HTML y definir múltiples [plantillas HTML](https://developer.mozilla.org/docs/Web/HTML/Element/template) usando el elemento `<template>`. Una plantilla es un bloque HTML reutilizable que el navegador no muestra y debe instanciarse en tiempo de ejecución mediante JavaScript.
### Tarea:
Crearemos una aplicación bancaria con dos pantallas: la página de inicio de sesión y el panel de control. Primero, agreguemos en el cuerpo HTML un elemento de marcador de posición que usaremos para instanciar las diferentes pantallas de nuestra aplicación:
```html
<div id="app">Loading...</div>
```
Le daremos un `id` para que sea más fácil localizarlo con JavaScript más adelante.
> Consejo: dado que el contenido de este elemento será reemplazado, podemos poner un mensaje de carga o un indicador que se mostrará mientras se carga la aplicación.
A continuación, agreguemos debajo la plantilla HTML para la página de inicio de sesión. Por ahora, solo pondremos allí un título y una sección que contiene un botón que usaremos para realizar la navegación.
```html
<template id="login">
<h1>Bank App</h1>
<section>
<button>Login</button>
</section>
</template>
```
Luego agregaremos otra plantilla HTML para la página del tablero. Esta página contendrá diferentes secciones:
- Un encabezado con un título y un botón para cerrar sesión
- El saldo actual de la cuenta bancaria
- Una lista de transacciones, que se muestra en una tabla.
```html
<template id="dashboard">
<header>
<h1>Bank App</h1>
<button>Logout</button>
</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>
```
Sugerencia: al crear plantillas HTML, si desea ver cómo se verá, puede comentar las líneas `<template>` y `</template>` encerrándolas entre `<!-- -->`.
✅ ¿Por qué crees que usamos atributos ʻid` en las plantillas? ¿Podríamos usar algo más como clases?
## Visualización de plantillas con JavaScript
Si prueba su archivo HTML actual en un navegador, verá que se atasca mostrando `Loading...`. Eso es porque necesitamos agregar código JavaScript para crear instancias y mostrar las plantillas HTML.
La instanciación de una plantilla se suele realizar en 3 pasos:
1. Recupere el elemento de plantilla en el DOM, por ejemplo, usando [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Clone el elemento de plantilla, usando [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
3. Adjúntelo al DOM bajo un elemento visible, por ejemplo usando [ʻappendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild).
✅ ¿Por qué necesitamos clonar la plantilla antes de adjuntarla al DOM? ¿Qué crees que pasaría si nos salteáramos este paso?
### Tarea
Cree un nuevo archivo llamado `app.js` en la carpeta de su proyecto e importe ese archivo en la sección `<head>` de su HTML:
```html
<script src="app.js" defer></script>
```
Ahora en `app.js`, crearemos una nueva función `updateRoute`:
```js
function updateRoute(templateId) {
const template = document.getElementById(templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
```
Lo que hacemos aquí son exactamente los 3 pasos descritos anteriormente. Instalamos la plantilla con el id `templateId` y colocamos su contenido clonado dentro de nuestro marcador de posición de la aplicación. Tenga en cuenta que necesitamos usar `cloneNode (true)` para copiar todo el subárbol de la plantilla.
Ahora llame a esta función con una de las plantillas y observe el resultado.
```js
updateRoute('login');
```
✅ ¿Cuál es el propósito de este código `app.innerHTML = '';`? ¿Qué pasa sin él?
## Creando rutas
Cuando hablamos de una aplicación web, llamamos *Enrutamiento* la intención de asignar **URL** a pantallas específicas que deben mostrarse. En un sitio web con varios archivos HTML, esto se hace automáticamente ya que las rutas de los archivos se reflejan en la URL. Por ejemplo, con estos archivos en la carpeta de su proyecto:
```
mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html
```
Si crea un servidor web con `mywebsite` como raíz, la asignación de URL será:
```
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
```
Sin embargo, para nuestra aplicación web estamos usando un solo archivo HTML que contiene todas las pantallas, por lo que este comportamiento predeterminado no nos ayudará. Tenemos que crear este mapa manualmente y actualizar la plantilla mostrada usando JavaScript.
### Tarea
Usaremos un objeto simple para implementar un [mapa](https://en.wikipedia.org/wiki/Associative_array) entre las rutas de URL y nuestras plantillas. Agregue este objeto en la parte superior de su archivo `app.js`.
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
Ahora modifiquemos un poco la función `updateRoute`. En lugar de pasar directamente el `templateId` como argumento, queremos recuperarlo mirando primero la URL actual y luego usar nuestro mapa para obtener el valor de ID de plantilla correspondiente. Podemos usar [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) para obtener solo la sección de ruta de la URL.
```js
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);
}
```
Aquí mapeamos las rutas que declaramos a la plantilla correspondiente. Puede probar que funciona correctamente cambiando la URL manualmente en su navegador.
✅ ¿Qué sucede si ingresa una ruta desconocida en la URL? ¿Cómo podríamos solucionar esto?
## Añadiendo navegación
El siguiente paso para nuestra aplicación es agregar la posibilidad de navegar entre páginas sin tener que cambiar la URL manualmente. Esto implica dos cosas:
1. Actualización de la URL actual
2. Actualización de la plantilla mostrada en función de la nueva URL
Ya nos ocupamos de la segunda parte con la función `updateRoute`, así que tenemos que averiguar cómo actualizar la URL actual.
Si bien el elemento de anclaje HTML [`<a>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) se puede utilizar para crear hipervínculos a diferentes URL, podemos ' No use eso aquí, ya que hará que el navegador vuelva a cargar el HTML.
En su lugar, tendremos que usar JavaScript y más específicamente el [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) que permite actualizar la URL y cree una nueva entrada en el historial de navegación, sin volver a cargar el HTML.
### Tarea
Creemos una nueva función que podamos usar para navegar en nuestra aplicación:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
Este método primero actualiza la URL actual según la ruta proporcionada y luego actualiza la plantilla. La propiedad `window.location.origin` devuelve la raíz de la URL, lo que nos permite reconstruir una URL completa a partir de una ruta determinada.
Ahora que tenemos esta función, podemos solucionar el problema que tenemos si una ruta no coincide con ninguna ruta definida. Modificaremos la función `updateRoute` agregando un respaldo a una de las rutas existentes si no podemos encontrar una coincidencia.
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
Si no se puede encontrar una ruta, ahora lo redireccionaremos a la página de `login`.
Completemos el sistema de navegación agregando enlaces a nuestros botones *login* y *logout* en el HTML.
```html
<button onclick="navigate('/dashboard')">Login</button>
...
<button onclick="navigate('/login')">Logout</button>
```
Usando el atributo [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) enlaza el evento `click` al código JavaScript, aquí la llamada al` navigate()`función.
Intente hacer clic en estos botones, ahora debería poder navegar entre las diferentes pantallas de su aplicación.
✅ El método `history.pushState` es parte del estándar HTML5 y está implementado en [todos los navegadores modernos](https://caniuse.com/?search=pushState). Si está creando una aplicación web para navegadores más antiguos, hay un truco que puede usar en lugar de esta API: usar un [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) antes la ruta puede implementar un enrutamiento que funcione con la navegación de anclaje regular y no recargue la página, ya que su propósito era crear enlaces internos dentro de una página.
## Manejo de los botones de avance y retroceso del navegador
El uso de `history.pushState` crea nuevas entradas en el historial de navegación del navegador. Puede verificar que manteniendo presionado el *botón de retroceso* de su navegador, debería mostrar algo como esto:
![Captura de pantalla del historial de navegación](../history.png)
Si intenta hacer clic en el botón Atrás varias veces, verá que la URL actual cambia y el historial se actualiza, pero se sigue mostrando la misma plantilla.
Eso es porque no sabemos que necesitamos llamar a `updateRoute()` cada vez que cambia el historial. Si echas un vistazo a la [`history.pushState` documentation](https://developer.mozilla.org/docs/Web/API/History/pushState), puedes ver que si el estado cambia - lo que significa que nos mudamos a una URL diferente - se activa el evento [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event). Lo usaremos para solucionar ese problema.
### Tarea
Para asegurarnos de que la plantilla mostrada se actualice cuando cambie el historial del navegador, adjuntaremos una nueva función que llama a `updateRoute()`. Lo haremos en la parte inferior de nuestro archivo `app.js`:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> Nota: utilizamos una [función de flecha](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) aquí para declarar nuestro controlador de eventos `popstate` por concisión, pero la función regular funcionaría igual.
[![Arrow Functions](https://img.youtube.com/vi/JiXY9wlqUxQ/0.jpg)](https://youtube.com/watch?v=JiXY9wlqUxQ "Arrow Functions")
Ahora intente utilizar los botones de avance y retroceso de sus navegadores y compruebe que esta vez lo que se muestra está actualizado correctamente.
---
## 🚀 Desafío
Agregue una nueva plantilla y ruta para una tercera página que muestre los créditos de esta aplicación.
## [Post-lecture prueba](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42)
## Revisión y autoestudio
**Tarea**: [Mejorar el enrutamiento](assignment.es.md)

View File

@@ -1,309 +0,0 @@
# Créer une application bancaire Partie 1 : Modèles HTML et routages dans une application Web
## Quiz préalable
[Quiz préalable](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41?loc=fr)
### Introduction
Depuis l'avènement de JavaScript dans les navigateurs, les sites Web deviennent plus interactifs et complexes que jamais. Les technologies Web sont maintenant couramment utilisées pour créer des applications entièrement fonctionnelles qui s'exécutent directement dans un navigateur que nous appelons [applications Web](https://en.wikipedia.org/wiki/Web_application). Les applications Web étant hautement interactives, les utilisateurs ne souhaitent pas attendre un rechargement complet de la page à chaque fois qu'une action est effectuée. C'est pourquoi JavaScript est utilisé pour mettre à jour le HTML directement à l'aide du DOM, afin de fournir une expérience utilisateur plus fluide.
Dans cette leçon, nous allons poser les bases de la création d'une application Web bancaire, en utilisant des modèles HTML pour créer plusieurs écrans pouvant être affichés et mis à jour sans avoir à recharger toute la page HTML.
### Prérequis
Vous avez besoin d'un serveur Web local pour tester l'application Web que nous allons créer dans cette leçon. Si vous n'en avez pas, vous pouvez installer [Node.js](https://nodejs.org/fr) et utiliser la commande `npx lite-server` depuis le dossier de votre projet. Il créera un serveur Web local et ouvrira votre application dans un navigateur.
### Préparation
Sur votre ordinateur, créez un dossier nommé `bank` avec un fichier nommé `index.html` à l'intérieur. Nous allons commencer par ce code HTML [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code):
```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>
```
---
## Modèles HTML
Si vous souhaitez créer plusieurs écrans pour une page Web, une solution serait de créer un fichier HTML pour chaque écran que vous souhaitez afficher. Cependant, cette solution présente quelques inconvénients :
- Vous devez recharger l'intégralité du code HTML lors du changement d'écran, ce qui peut être lent.
- Il est difficile de partager des données entre les différents écrans.
Une autre approche consiste à n'avoir qu'un seul fichier HTML et à définir plusieurs [modèles HTML](https://developer.mozilla.org/docs/Web/HTML/Element/template) à l'aide de l'élément `<template>`. Un modèle est un bloc HTML réutilisable qui n'est pas affiché par le navigateur et doit être instancié lors de l'exécution à l'aide de JavaScript.
### Tâche
Nous allons créer une application bancaire avec deux écrans : la page de connexion et le tableau de bord. Tout d'abord, ajoutons dans le corps HTML un élément d'espace réservé que nous utiliserons pour instancier les différents écrans de notre application :
```html
<div id="app">Loading...</div>
```
Nous lui donnons un `id` pour le rendre plus facile à localiser avec JavaScript plus tard.
> Astuce : puisque le contenu de cet élément sera remplacé, nous pouvons mettre un message de chargement ou un indicateur qui s'affichera pendant le chargement de l'application.
Ensuite, ajoutons ci-dessous le modèle HTML pour la page de connexion. Pour l'instant nous n'y mettrons qu'un titre et une section contenant un lien que nous utiliserons pour effectuer la navigation.
```html
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
```
Ensuite, nous ajouterons un autre modèle HTML pour la page du tableau de bord. Cette page contiendra différentes sections :
- Une en-tête avec un titre et un lien de déconnexion
- Le solde courant du compte bancaire
- Une liste des transactions, affichée dans un tableau
```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>
```
> Astuce : lors de la création de modèles HTML, si vous voulez voir à quoi cela ressemblera, vous pouvez commenter les lignes `<template>` et `</template>` en les entourant de `<!-- -->`.
✅ Pourquoi pensez-vous que nous utilisons les attributs `id` sur les modèles ? Pourrions-nous utiliser autre chose comme des classes ?
## Afficher des modèles avec JavaScript
Si vous essayez votre fichier HTML actuel dans un navigateur, vous verrez qu'il reste bloqué en affichant `Loading...`. C'est parce que nous devons ajouter du code JavaScript pour instancier et afficher les modèles HTML.
L'instanciation d'un modèle se fait généralement en 3 étapes :
1. Récupérez l'élément du modèle dans le DOM, par exemple en utilisant [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Clonez l'élément de modèle à l'aide de [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
3. Attachez-le au DOM sous un élément visible, par exemple en utilisant [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild).
✅ Pourquoi avons-nous besoin de cloner le modèle avant de l'attacher au DOM ? Que pensez-vous qu'il se passerait si nous sautions cette étape?
### Tâche
Créez un nouveau fichier nommé `app.js` dans votre dossier de projet et importez ce fichier dans la section `<head>` de votre code HTML :
```html
<script src="app.js" defer></script>
```
Maintenant dans `app.js`, nous allons créer une nouvelle fonction `updateRoute`:
```js
function updateRoute(templateId) {
const template = document.getElementById(templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
```
Ce que nous faisons ici est exactement les 3 étapes décrites ci-dessus. Nous instancions le modèle avec l'ID `templateId` et plaçons son contenu cloné dans notre espace réservé d'application. Notez que nous devons utiliser `cloneNode(true)` pour copier l'intégralité du sous-arbre du modèle.
Appelez maintenant cette fonction avec l'un des modèles et regardez le résultat.
```js
updateRoute('login');
```
✅ Quel est le but de ce code `app.innerHTML = '';` ? Que se passe-t-il sans ?
## Création de routes
Lorsque nous parlons d'une application Web, nous appelons *Routage* l'intention de mapper des **URL** sur des écrans spécifiques qui doivent être affichés. Sur un site Web avec plusieurs fichiers HTML, cela se fait automatiquement car les chemins d'accès aux fichiers sont reflétés sur l'URL. Par exemple, avec ces fichiers dans votre dossier de projet :
```
monsite/index.html
monsite/login.html
monsite/admin/index.html
```
Si vous créez un serveur Web avec `mywebsite` comme racine, le mappage d'URL sera:
```
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
```
Cependant, pour notre application Web, nous utilisons un seul fichier HTML contenant tous les écrans, ce comportement par défaut ne nous aidera donc pas. Nous devons créer cette carte manuellement et effectuer la mise à jour du modèle affiché à l'aide de JavaScript.
### Tâche
Nous utiliserons un objet simple pour implémenter une [carte](https://en.wikipedia.org/wiki/Associative_array) entre les chemins d'URL et nos modèles. Ajoutez cet objet en haut de votre fichier `app.js`.
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
Modifions maintenant un peu la fonction `updateRoute`. Au lieu de passer directement le `templateId` comme argument, nous voulons le récupérer en regardant d'abord l'URL actuelle, puis en utilisant notre carte pour obtenir la valeur d'ID de modèle correspondante. Nous pouvons utiliser [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) pour obtenir uniquement la section du chemin de l'URL.
```js
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);
}
```
Ici, nous avons mappé les routes que nous avons déclarées au modèle correspondant. Vous pouvez vérifier que celà fonctionne correctement en modifiant l'URL manuellement dans votre navigateur.
✅ Que se passe-t-il si vous saisissez un chemin inconnu dans l'URL ? Comment pourrions-nous résoudre cela?
## Ajout de navigation
La prochaine étape pour notre application consiste à ajouter la possibilité de naviguer entre les pages sans avoir à modifier l'URL manuellement. Cela implique deux choses :
1. Mise à jour de l'URL actuelle
2. Mise à jour du modèle affiché en fonction de la nouvelle URL
Nous nous sommes déjà occupés de la deuxième partie avec la fonction `updateRoute`, nous devons donc trouver comment mettre à jour l'URL actuelle.
Il va falloir utiliser JavaScript et plus précisément le [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) qui permet de mettre à jour l'URL et créer une nouvelle entrée dans l'historique de navigation, sans recharger le code HTML.
> Remarque : Bien que l'élément d'ancrage HTML [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) puisse être utilisé seul pour créer des liens hypertexte à des URL différentes, il fera le navigateur recharger le HTML par défaut. Il est nécessaire d'empêcher ce comportement lors de la gestion du routage avec un javascript personnalisé, en utilisant la fonction preventDefault() sur l'événement click.
### Tâche
Créons une nouvelle fonction que nous pouvons utiliser pour naviguer dans notre application:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
Cette méthode met d'abord à jour l'URL actuelle en fonction du chemin donné, puis met à jour le modèle. La propriété `window.location.origin` renvoie la racine de l'URL, nous permettant de reconstruire une URL complète à partir d'un chemin donné.
Maintenant que nous avons cette fonction, nous pouvons résoudre le problème que nous avons si un chemin ne correspond à aucun itinéraire défini. Nous modifierons la fonction `updateRoute` en ajoutant une solution de secours à l'une des routes existantes si nous ne trouvons pas de correspondance.
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
Si un itinéraire ne peut pas être trouvé, nous allons maintenant rediriger vers la page de `login`.
Créons maintenant une fonction pour obtenir l'URL lorsqu'un lien est cliqué et pour empêcher le comportement de lien par défaut du navigateur :
```js
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
```
Complétons le système de navigation en ajoutant des liens à nos liens *Login* et *Logout* dans le HTML.
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
L'objet `event` ci-dessus capture l'événement `click` et le transmet à notre fonction `onLinkClick`.
Utiliser l'attribut [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) lie l'événement `click` au code JavaScript, dans ce cas via l'appel à la fonction `navigate ()`.
Essayez de cliquer sur ces liens, vous devriez maintenant pouvoir naviguer entre les différents écrans de votre application.
✅ La méthode `history.pushState` fait partie de la norme HTML5 et est implémentée dans [tous les navigateurs modernes](https://caniuse.com/?search=pushState). Si vous créez une application Web pour les navigateurs plus anciens, il existe une astuce que vous pouvez utiliser à la place de cette API : en utilisant un [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) avant le chemin que vous pouvez implémenter un routage qui fonctionne avec la navigation d'ancrage standard et ne recharge pas la page, car son but était de créer des liens internes au sein d'une page.
## Gestion des boutons Précédent et Suivant du navigateur
L'utilisation de `history.pushState` crée de nouvelles entrées dans l'historique de navigation du navigateur. Vous pouvez vérifier qu'en maintenant enfoncé le *bouton de retour* de votre navigateur, il devrait afficher quelque chose comme ceci:
![Capture d'écran de l'historique de navigation](./history.png)
Si vous essayez de cliquer plusieurs fois sur le bouton Précédent, vous verrez que l'URL actuelle change et que l'historique est mis à jour, mais le même modèle reste affiché.
C'est parce que l'application ne sait pas que nous devons appeler `updateRoute()` chaque fois que l'historique change. Si vous jetez un oeil à [ `la documentation de history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), vous pouvez voir que si l'état change - c'est que nous sommes passés à une URL différente - l'événement [ `popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) est déclenché. Nous allons l'utiliser pour résoudre ce problème.
### Tâche
Pour nous assurer que le modèle affiché est mis à jour lorsque l'historique du navigateur change, nous allons attacher une nouvelle fonction qui appelle `updateRoute()`. Nous le ferons au bas de notre fichier `app.js`:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> Remarque : nous avons utilisé une [fonction fléchée](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) ici pour déclarer notre gestionnaire d'événements `popstate` pour plus de concision, mais un la fonction normale fonctionnerait de la même manière.
Voici une vidéo de rappel sur les fonctions fléchées :
[![Fonctions fléchées](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Fonctions fléchées")
> 🎥 Cliquez sur l'image ci-dessus pour une vidéo sur les fonctions fléchées.
Essayez maintenant d'utiliser les boutons Précédent et Suivant de vos navigateurs, et vérifiez que la route affichée est bien mis à jour cette fois.
---
## 🚀 Défi
Ajoutez un nouveau modèle et une route pour une troisième page qui affiche les crédits de cette application.
## Quiz de validation des connaissances
[Quiz de validation des connaissances](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42?loc=fr)
## Révision et étude personnelle
Le routage est l'une des parties étonnamment délicates du développement Web, d'autant plus que le Web passe des comportements d'actualisation des pages aux actualisations des pages d'application à page unique. En savoir plus sur [comment le service Azure Static Web App](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon) gère le routage . Pouvez-vous expliquer pourquoi certaines des décisions décrites dans ce document sont nécessaires?
## Affectation
[Améliorer le routage](assignment.fr.md)

View File

@@ -1,304 +0,0 @@
# एक वेब ऐप में बैंकिंग ऐप पार्ट 1: HTML टेम्प्लेट और रूट बनाएं
## पूर्व व्याख्यान प्रश्नोत्तरी
[पूर्व व्याख्यान प्रश्नोत्तरी](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41?loc=hi)
### परिचय
ब्राउज़रों में जावास्क्रिप्ट के आगमन के बाद से, वेबसाइटें पहले से कहीं अधिक इंटरैक्टिव और जटिल होती जा रही हैं। वेब प्रौद्योगिकियों का अब आमतौर पर पूरी तरह कार्यात्मक अनुप्रयोग बनाने के लिए उपयोग किया जाता है जो सीधे एक ब्राउज़र में चलता है जिसे हम [वेब एप्लिकेशन](https://en.wikipedia.org/wiki/Web_application) कहते हैं। चूंकि वेब ऐप्स अत्यधिक संवादात्मक हैं, इसलिए उपयोगकर्ता हर बार किसी क्रिया के पूरा होने तक पूर्ण पृष्ठ पुनः लोड होने की प्रतीक्षा नहीं करना चाहते हैं। यही कारण है कि एक चिकनी उपयोगकर्ता अनुभव प्रदान करने के लिए जावास्क्रिप्ट का उपयोग सीधे डोम का उपयोग करके HTML को अपडेट करने के लिए किया जाता है।
इस पाठ में, हम बैंक वेब ऐप बनाने के लिए नींव रखने जा रहे हैं, HTML टेम्प्लेट का उपयोग करके ऐसी कई स्क्रीन बना सकते हैं जिन्हें प्रदर्शित किया जा सकता है और पूरे HTML पृष्ठ को फिर से लोड किए बिना अपडेट किया जा सकता है।
### शर्त
इस पाठ में हमारे द्वारा बनाए गए वेब ऐप का परीक्षण करने के लिए आपको एक स्थानीय वेब सर्वर की आवश्यकता होगी। यदि आपके पास एक नहीं है, तो आप [Node.js](https://nodejs.org) को स्थापित कर सकते हैं और अपने प्रोजेक्ट फ़ोल्डर से कमांड `npx lite-server` का उपयोग कर सकते हैं। यह एक स्थानीय वेब सर्वर बनाएगा और आपके ऐप को एक ब्राउज़र में खोलेगा।
### तैयारी
अपने कंप्यूटर पर, उसके अंदर `index.html` नामक फ़ाइल के साथ `bank` नामक एक फ़ोल्डर बनाएँ। हम इस HTML [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code) से शुरू करेंगे :
```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 फ़ाइल है, और `<template>` तत्व का उपयोग करके कई [HTML टेम्पलेट्स](https://developer.mozilla.org/docs/Web/HTML/Element/template) को परिभाषित करें। एक टेम्पलेट एक पुन: प्रयोज्य HTML ब्लॉक है जो ब्राउज़र द्वारा प्रदर्शित नहीं किया जाता है, और जावास्क्रिप्ट का उपयोग करके रनटाइम पर तत्काल किया जाना चाहिए।
### टास्क
हम दो स्क्रीन के साथ एक बैंक ऐप बनाएंगे: लॉगिन पेज और डैशबोर्ड। सबसे पहले, एचटीएमएल बॉडी में एक प्लेसहोल्डर तत्व जोड़ें, जिसका उपयोग हम अपने ऐप की विभिन्न स्क्रीन को इंस्टेंट करने के लिए करेंगे:
```html
<div id="app">Loading...</div>
```
हम इसे एक `id` दे रहे हैं ताकि बाद में इसे जावास्क्रिप्ट के साथ ढूंढना आसान हो सके।
> युक्ति: चूंकि इस तत्व की सामग्री को बदल दिया जाएगा, हम एक लोडिंग संदेश या संकेतक में डाल सकते हैं जो ऐप लोड होने के दौरान दिखाया जाएगा।
अगला, लॉगिन पृष्ठ के लिए HTML टेम्पलेट के नीचे जोड़ें। अभी के लिए हम केवल एक शीर्षक और एक अनुभाग रखेंगे जिसमें एक लिंक होगा जिसका उपयोग हम नेविगेशन करने के लिए करेंगे।
```html
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
```
फिर हम डैशबोर्ड पृष्ठ के लिए एक और HTML टेम्पलेट जोड़ेंगे। इस पृष्ठ में विभिन्न अनुभाग होंगे:
- शीर्षक के साथ हैडर और लॉगआउट लिंक
- बैंक खाते का वर्तमान संतुलन
- लेनदेन की एक सूची, एक तालिका में प्रदर्शित
```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` विशेषताओं का उपयोग क्यों करते हैं? क्या हम कक्षाओं की तरह कुछ और उपयोग कर सकते हैं?
## जावास्क्रिप्ट के साथ टेम्पलेट्स प्रदर्शित करना
यदि आप अपनी वर्तमान HTML फ़ाइल को किसी ब्राउज़र में आज़माते हैं, तो आप देखेंगे कि यह `Loading...` को प्रदर्शित करता है। ऐसा इसलिए है क्योंकि हमें HTML टेम्प्लेट को इंस्टेंट करने और प्रदर्शित करने के लिए कुछ जावास्क्रिप्ट कोड जोड़ना होगा।
एक टेम्पलेट को तत्काल बनाना आमतौर पर 3 चरणों में किया जाता है:
1. DOM में टेम्पलेट तत्व को पुनः प्राप्त करें, उदाहरण के लिए [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getEgetById) का उपयोग करके।
2. टेम्पलेट तत्व को क्लोन करें, [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode) का उपयोग करके।
3. इसे एक दृश्य तत्व के तहत DOM में संलग्न करें, उदाहरण के लिए [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild) का उपयोग करके।
✅ DOM को संलग्न करने से पहले हमें टेम्प्लेट को क्लोन करने की आवश्यकता क्यों है? आपको क्या लगता है कि अगर हम इस कदम को छोड़ देते तो क्या होता?
### टास्क
अपने प्रोजेक्ट फ़ोल्डर में `app.js` नामक एक नई फ़ाइल बनाएँ और उस फ़ाइल को अपने HTML के `<head>`अनुभाग में आयात करें:
```html
<script src="app.js" defer></script>
```
अब `app.js` में, हम एक नया फ़ंक्शन `updateRoute` बनाएंगे:
```js
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 चरण हैं। हम आईडी `templateId` के साथ टेम्पलेट को इंस्टेंट करते हैं, और हमारे ऐप प्लेसहोल्डर के भीतर इसकी क्लोन सामग्री डालते हैं। ध्यान दें कि हमें टेम्पलेट के पूरे उपप्रकार को कॉपी करने के लिए `cloneNode(true)` का उपयोग करने की आवश्यकता है।
अब इस फंक्शन को टेम्प्लेट में से किसी एक पर कॉल करें और परिणाम देखें।
```js
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 फ़ाइल का उपयोग कर रहे हैं ताकि यह डिफ़ॉल्ट व्यवहार हमारी मदद न करे। हमें इस नक्शे को मैन्युअल रूप से बनाना होगा और जावास्क्रिप्ट का उपयोग करके प्रदर्शित टेम्प्लेट को अपडेट करना होगा।
### टास्क
URL पथ और हमारे टेम्प्लेट के बीच एक [मैप](https://en.wikipedia.org/wiki/Associative_array) को लागू करने के लिए हम एक साधारण वस्तु का उपयोग करेंगे। इस ऑब्जेक्ट को अपने `app.js` फ़ाइल के शीर्ष पर जोड़ें।
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
अब चलो `updateRoute` फ़ंक्शन को थोड़ा संशोधित करते हैं। एक तर्क के रूप में सीधे `templateId` पास करने के बजाय, हम पहले वर्तमान URL को देखकर इसे पुनः प्राप्त करना चाहते हैं, और फिर संबंधित टेम्पलेट आईडी मान प्राप्त करने के लिए हमारे मानचित्र का उपयोग करते हैं। URL से केवल पथ अनुभाग प्राप्त करने के लिए हम [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) का उपयोग कर सकते हैं।
```js
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 को कैसे अपडेट किया जाए।
हमें जावास्क्रिप्ट और अधिक विशेष रूप से [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) का उपयोग करना होगा जो URL को अपडेट करने की अनुमति देता है HTML को पुनः लोड किए बिना, ब्राउज़िंग इतिहास में एक नई प्रविष्टि बनाएँ।
> नोट: जबकि HTML एंकर तत्व [`<a href>`] (https://developer.mozilla.org/docs/Web/HTML/Element/a) का उपयोग हाइपरलिंक बनाने के लिए स्वयं किया जा सकता है विभिन्न यूआरएल, यह ब्राउज़र को डिफ़ॉल्ट रूप से HTML को फिर से लोड करेगा। क्लिक करें घटना पर preventDefault() फ़ंक्शन का उपयोग करके कस्टम जावास्क्रिप्ट के साथ रूटिंग को हैंडल करते समय इस व्यवहार को रोकना आवश्यक है।
### टास्क
आइए एक नया फ़ंक्शन बनाएं जिसे हम अपने ऐप में नेविगेट करने के लिए उपयोग कर सकते हैं:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
यह विधि पहले दिए गए पथ के आधार पर वर्तमान URL को अपडेट करती है, फिर टेम्पलेट को अपडेट करती है। प्रॉपर्टी `window.location.origin` URL रूट लौटाती है, जिससे हम किसी दिए गए पथ से एक पूर्ण URL का पुनर्निर्माण कर सकते हैं।
अब जब हमारे पास यह फ़ंक्शन है, तो हम इस समस्या का ध्यान रख सकते हैं कि अगर कोई रास्ता किसी परिभाषित मार्ग से मेल नहीं खाता है। यदि हम एक मैच नहीं पा सकते हैं, तो हम मौजूदा मार्ग में से किसी एक में वापसी को जोड़कर `updateRoute` फ़ंक्शन को संशोधित करेंगे।
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
यदि कोई मार्ग नहीं मिल रहा है, तो हम अब `login` पेज पर रीडायरेक्ट करेंगे।
Now let's create a function to get the URL when a link is clicked, and to prevent the browser's default link behavior:
```js
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
```
HTML में हमारे *लॉगिन* और *लॉगआउट* लिंक से बाइंडिंग जोड़कर नेविगेशन सिस्टम को पूरा करें।
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
[`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) विशेषता का उपयोग करके जावास्क्रिप्ट कोड पर `click` ईवेंट को बांधें, यहाँ `navigate()` फ़ंक्शन पर कॉल करें।
इन लिंक पर क्लिक करने का प्रयास करें, अब आपको अपने ऐप के विभिन्न स्क्रीन के बीच नेविगेट करने में सक्षम होना चाहिए।
`History.pushState` विधि HTML5 मानक का हिस्सा है और [सभी आधुनिक ब्राउज़रों](https://caniuse.com/?search=pushState) में लागू किया गया है। यदि आप पुराने ब्राउज़रों के लिए एक वेब ऐप बना रहे हैं, तो इस एपीआई के स्थान पर आप एक ट्रिक का उपयोग कर सकते हैं: इससे पहले [हैश (`#`)](https://en.wikipedia.org/wiki/URI_fragment) का उपयोग कर पथ आप नियमित एंकर नेविगेशन के साथ काम करने वाले रूटिंग को लागू कर सकते हैं और पृष्ठ को फिर से लोड नहीं करते हैं, क्योंकि इसका उद्देश्य एक पृष्ठ के भीतर आंतरिक लिंक बनाना था।
## ब्राउजर के बैक और फॉरवर्ड बटन को हैंडल करना
`History.pushState` का उपयोग करके ब्राउज़र के नेविगेशन इतिहास में नई प्रविष्टियाँ बनाता है। आप देख सकते हैं कि आपके ब्राउज़र का *बैक बटन* पकड़कर, इसे कुछ इस तरह प्रदर्शित करना चाहिए:
![नेविगेशन इतिहास का स्क्रीनशॉट](../history.png)
यदि आप कुछ बार बैक बटन पर क्लिक करने का प्रयास करते हैं, तो आप देखेंगे कि वर्तमान URL बदल जाता है और इतिहास अपडेट हो जाता है, लेकिन वही टेम्पलेट प्रदर्शित होता रहता है।
ऐसा इसलिए है क्योंकि हमें नहीं पता है कि इतिहास बदलने के लिए हमें हर बार `updateRoute()` को कॉल करना होगा। यदि आप [`history.pushState` दस्तावेज़ीकरण](https://developer.mozilla.org/docs/Web/API/History/pushState) पर एक नज़र डालते हैं, तो आप देख सकते हैं कि यदि राज्य बदलता है - इसका अर्थ है कि हम एक अलग URL पर चले गए - [`popstate`] (https://developer.mozilla.org/docs/Web/API/Window/popstate_event) इवेंट ट्रिगर है। हम उस समस्या को ठीक करने के लिए इसका उपयोग करेंगे।
### टास्क
यह सुनिश्चित करने के लिए कि ब्राउज़र इतिहास में परिवर्तन होने पर प्रदर्शित टेम्प्लेट को अपडेट किया जाता है, हम एक नया फ़ंक्शन संलग्न करेंगे जो `updateRoute()` कहता है। हम अपने `app.js` फ़ाइल के नीचे करेंगे:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> नोट: हमने एक [एरो फंक्शन](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Reference/Arrow_functions) का इस्तेमाल किया है ताकि हम अपने `poopstate` ईवेंट हैंडलर को संक्षिप्तता के लिए घोषित कर सकें, लेकिन नियमित कार्य एक ही काम करेगा।
यहां एरो फंक्शन पर एक ताज़ा वीडियो है:
[![एरो फंक्शन](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "एरो फंक्शन")
> तीर के कार्यों के बारे में वीडियो के लिए ऊपर दी गई छवि पर क्लिक करें।
अब अपने ब्राउज़र के बैक और फ़ॉरवर्ड बटन का उपयोग करने का प्रयास करें, और जांचें कि इस बार प्रदर्शित मार्ग सही ढंग से अपडेट किया गया है।
---
## 🚀 चुनौती
तीसरे पृष्ठ के लिए एक नया टेम्प्लेट और रूट जोड़ें जो इस ऐप के लिए क्रेडिट दिखाता है।
## व्याख्यान उपरांत प्रश्नोत्तरी
[व्याख्यान उपरांत प्रश्नोत्तरी](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42?loc=hi)
## समीक्षा और स्व अध्ययन
रूटिंग वेब विकास के आश्चर्यजनक रूप से मुश्किल भागों में से एक है, विशेष रूप से वेब पेज रीफ्रेश बिहेवियर से लेकर सिंगल पेज एप्लीकेशन पेज रिफ्रेश तक चलता है। [कैसे Azure स्टेटिक वेब ऐप सेवा](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon) के बारे में थोड़ा पढ़ें रूटिंग । क्या आप बता सकते हैं कि उस दस्तावेज़ पर वर्णित कुछ निर्णय क्यों आवश्यक हैं?
## असाइनमेंट
[रूटिंग में सुधार करें](assignment.hi.md)

View File

@@ -1,306 +0,0 @@
# Creazione di un'App Bancaria Parte 1: Modelli HTML e Rotte in un'app web
## Quiz Pre-Lezione
[Quiz Pre-Lezione](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41?loc=it)
### Introduzione
Dall'avvento di JavaScript nei browser, i siti web stanno diventando più interattivi e complessi che mai. Le tecnologie web sono ora comunemente utilizzate per creare applicazioni completamente funzionali che vengono eseguite direttamente in un browser che vengono chiamate [applicazioni web](https://it.wikipedia.org/wiki/Applicazione_web). Poiché le app web sono altamente interattive, gli utenti non desiderano attendere il ricaricamento di una pagina intera ogni volta che viene eseguita un'azione. Ecco perché JavaScript viene utilizzato per aggiornare l'HTML direttamente utilizzando il DOM, per fornire un'esperienza utente più fluida.
In questa lezione, getteremo le basi per creare un'app web bancaria, utilizzando modelli HTML per creare più schermate che possono essere visualizzate e aggiornate senza dover ricaricare l'intera pagina HTML.
### Prerequisito
È necessario un server web locale per testare l'app web che verrà creata in questa lezione. Se non ne ha uno, si può installare [Node.js](https://nodejs.org) e utilizzare il comando `npx lite-server` dalla cartella del progetto. Creerà un server web locale e aprirà la propria app in un browser.
### Preparazione
Sul proprio computer, creare una cartella denominata `bank` con un file denominato `index.html` al suo interno. Si inizierà da questo codice [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code) 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>
<!-- Qui è dove si lavorerà -->
</body>
</html>
```
---
## Modelli HTML.
Se si desidera creare più schermate per una pagina Web, una soluzione potrebbe essere la creazione di un file HTML per ogni schermata che si desidera visualizzare. Tuttavia, questa soluzione presenta alcuni inconvenienti:
- È necessario ricaricare l'intero HTML quando si cambia schermata, il che può essere lento.
- È difficile condividere i dati tra le diverse schermate.
Un altro approccio consiste nell'avere un solo file HTML e definire più [modelli HTML](https://developer.mozilla.org/docs/Web/HTML/Element/template) utilizzando l'elemento `<template>`. Un modello è un blocco HTML riutilizzabile che non viene visualizzato dal browser e deve essere istanziato in fase di esecuzione utilizzando JavaScript.
### Attività
Verrà creata un'app bancaria con due schermate: la pagina di accesso e il cruscotto. Innanzitutto, si aggiunge nel corpo dell'HTML un elemento segnaposto che si utilizzerà per istanziare le diverse schermate dell'app:
```html
<div id="app">Loading...</div>
```
Viene fornito un `ID` all'elemento per renderlo più facilmente individuabile con JavaScript in seguito.
> Suggerimento: poiché il contenuto di questo elemento verrà sostituito, si può inserire un messaggio di caricamento o un indicatore che verrà mostrato durante il caricamento dell'app.
Successivamente, si aggiunge il modello HTML seguente per la pagina di accesso. Per ora si inserirà solo un titolo e una sezione contenente un collegamento che si utilizzerà per eseguire la navigazione.
```html
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
```
Quindi si aggiungerà un altro modello HTML per la pagina del cruscotto. Questa pagina conterrà diverse sezioni:
- Un'intestazione con un titolo e un collegamento di disconnessione
- Saldo corrente del conto bancario
- Un elenco di transazioni, visualizzato in una tabella
```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>
```
> Suggerimento: durante la creazione di modelli HTML, se si vuole vedere come apparirà, si possono commentare le righe tra `<template>` `</template>` racchiudendole `tra <!- ->-->`.
✅ Perché si pensa che vengano utilizzati gli attributi `id` sui modelli? Si potrebbe usare qualcos'altro come le classi?
## Visualizzazione di modelli con JavaScript
Se si prova il proprio file HTML corrente in un browser, si vedrà che si blocca visualizzando `Loading ...` Questo perché si deve aggiungere del codice JavaScript per istanziare e visualizzare i modelli HTML.
L'istanza di un modello viene solitamente eseguita in 3 passaggi:
1. Recuperare l'elemento del modello nel DOM, ad esempio utilizzando [`document.getElementById`](https://developer.mozilla.org/it/docs/Web/API/Document/getElementById).
2. Clonare l'elemento template, usando [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
3. Collegarlo al DOM sotto un elemento visibile, ad esempio utilizzando [`appendChild`](https://developer.mozilla.org/it/docs/Web/API/Node/appendChild).
✅ Perché è necessario clonare il modello prima di collegarlo al DOM? Cosa si pensa che accadrebbe se venisse saltato questo passaggio?
### Attività
Creare un nuovo file denominato `app.js` nella cartella del progetto e importare quel file nella sezione `<head>` del proprio HTML:
```html
<script src="app.js" defer></script>
```
Ora in `app.js`, verrà creata una nuova funzione `updateRoute`:
```js
function updateRoute(templateId) {
const template = document.getElementById(templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
```
Quello che si fa qui sono esattamente i 3 passaggi descritti sopra. Si istanza il modello con l'id `templateId` e si inserisce il suo contenuto clonato nel segnaposto dell'app. Notare che si deve usare `cloneNode (true)` per copiare l'intero sottoalbero del modello.
Ora chiamare questa funzione con uno dei template e guardare il risultato.
```js
updateRoute('login');
```
✅ Qual è lo scopo di questo codice `app.innerHTML = '';`? Cosa succede senza di essa?
## Creazione di rotte
Quando si parla di un'app web, si definisce *Routing* (instradamento) l'intento di mappare gli **URL** a schermate specifiche che dovrebbero essere visualizzate. Su un sito web con più file HTML, questa operazione viene eseguita automaticamente poiché i percorsi dei file si riflettono sull'URL. Ad esempio, con questi file nella cartella del progetto:
```
mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html
```
Se si crea un server web con `mywebsite` come radice, la mappatura dell'URL sarà:
```
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
```
Tuttavia, per l'app web in costruzione si utilizza un singolo file HTML contenente tutte le schermate, quindi questo comportamento predefinito non sarà di aiuto. Si deve creare questa mappa manualmente ed eseguire l'aggiornamento del modello visualizzato utilizzando JavaScript.
### Attività
Si userà un semplice oggetto per implementare una [mappa](https://it.wikipedia.org/wiki/Array_associativo) tra i percorsi degli URL e i propri modelli. Aggiungere questo oggetto all'inizio del file `app.js`.
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
Ora modificare un po' la funzione `updateRoute`. Invece di passare direttamente il `templateId` come argomento, lo si vuole recuperare guardando prima l'URL corrente, quindi utilizzndo la mappa per ottenere il valore dell'ID del modello corrispondente. Si può usare [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) per ottenere solo la sezione del percorso dall'URL.
```js
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);
}
```
Qui sono state mappato le rotte che sono state dichiarate al modello corrispondente. Si può provare se funziona correttamente modificando manualmente l'URL nel proprio browser.
✅ Cosa succede se si inserisce un percorso sconosciuto nell'URL? Come potrebbe essere risolto questo problema?
## Aggiungere navigazione
Il prossimo passo per la costruzione dell'app è aggiungere la possibilità di navigare tra le pagine senza dover modificare manualmente l'URL. Questo implica due cose:
1. Aggiornamento dell'URL corrente
2. Aggiornamento del modello visualizzato in base al nuovo URL
E' già stata trattata la seconda parte con la funzione `updateRoute`, quindi occorre capire come aggiornare l'URL corrente.
Si dovrà utilizzare JavaScript e più precisamente [history.pushState](https://developer.mozilla.org/docs/Web/API/History/pushState) che permette di aggiornare l'URL e creare una nuova voce nella cronologia di navigazione, senza ricaricare l'HTML.
> Nota: Sebbene l'elemento HTML ancora [`<a href>`](https://developer.mozilla.org/it/docs/Web/HTML/Element/a) possa essere usato da solo per creare collegamenti ipertestuali a diversi URL, è anche in grado di fare ricaricare al browser l'HTML nella modalità predefinita. È necessario prevenire questo comportamento quando si gestisce il routing con javascript personalizzato, utilizzando la funzione preventDefault() sull'evento click.
### Attività
Si crea una nuova funzione da utilizzare per navigare nell'app:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
Questo metodo aggiorna prima l'URL corrente in base al percorso fornito, quindi aggiorna il modello. La proprietà `window.location.origin` restituisce l'URL radice, permettendo di ricostruire un URL completo da un dato percorso.
Ora che si ha questa funzione, ci si può occupare del problema che si verifica se un percorso non corrisponde a nessuna rotta definita. Si modificherà la funzione `updateRoute` aggiungendo una soluzione di contingenza per indirizzare verso una delle rotte esistenti se non viene trovata una corrispondenza.
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
Se non è possibile trovare una rotta, si esegue un reindirizzamento alla pagina `login`.
Ora si crea una funzione per ottenere l'URL quando si fa clic su un collegamento e per impedire il comportamento predefinito del browser per un collegamento:
```js
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
```
Si completa il sistema di navigazione aggiungendo collegamenti ai link di accesso (*Login*) e di disconnessione (*Logout*) nell'HTML.
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
Utilizzando l 'attributo [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) associare l'evento `click` al codice JavaScript, in questo caso la chiamata alla funzione `navigate()` .
Provare a fare clic su questi collegamenti, ora si dovrebbe essere in grado di navigare tra le diverse schermate dell'app.
✅ Il metodo `history.pushState` fa parte dello standard HTML5 e implementato in [tutti i browser moderni](https://caniuse.com/?search=pushState). Se si sta creando un'app web per browser meno recenti, c'è un trucco che si può usare al posto di questa API: usando un [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) prima del percorso si può implementare un instradatamento che funziona con la normale navigazione dell'elemento ancora e non ricarica la pagina, poiché il suo scopo era creare collegamenti all'interno di una pagina.
## Gestione dei pulsanti Avanti e Indietro del browser
L'utilizzo di `history.pushState` crea nuove voci nella cronologia di navigazione del browser. Si può verificare tenendo premuto il *pulsante Indietro* del proprio browser, dovrebbe visualizzare qualcosa del genere:
![Videata della cronologia di navigazione](../history.png)
Se si prova a fare clic sul pulsante Indietro alcune volte, si vedrà che l'URL corrente cambia e la cronologia viene aggiornata, ma lo stesso modello continua a essere visualizzato.
Questo perché il browser non sa che si deve chiamare `updateRoute()` ogni volta che cambia la cronologia. Se si dà un'occhiata alla documentazione di [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) si può vedere che se lo stato cambia, vale a dire che si è passati a un URL diverso, viene attivato l'[evento](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) `popstate`. Verrà usato per risolvere quel problema.
### Attività
Per assicurarsi che il modello visualizzato venga aggiornato quando la cronologia del browser cambia, si aggiungerà una nuova funzione che chiama `updateRoute()`. Verrà fatto in fondo al file `app.js`:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> Nota: è stata usata una [funzione freccia](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) qui per dichiarare il gestore di eventi `popstate` per concisione, ma una funzione normale andrebbe bene allo stesso modo.
Ecco un video di aggiornamento sulle funzioni freccia:
[![Funzionifreccia](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "")
> Fare clic sull'immagine sopra per un video sulle funzioni freccia
Ora provare a utilizzare i pulsanti Indietro e Avanti del proprio browser e controllare che il percorso visualizzato sia aggiornato correttamente questa volta.
---
## 🚀 Sfida
Aggiungere un nuovo modello e instradare per una terza pagina che mostra i crediti per questa app.
## Quiz Post-Lezione
[Quiz post-lezione](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42?loc=it)
## Revisione e Auto Apprendimento
Il routing (instradamento) è una delle parti sorprendentemente complicate dello sviluppo web, soprattutto perché il web passa dai comportamenti di aggiornamento della pagina all'aggiornamento della pagina dell'applicazione a pagina singola. Leggere alcune informazioni su [come il servizio App Web Static di Azure](https://docs.microsoft.com/azure/static-web-apps/routes?WT.mc_id=academic-4621-cxa) gestisce il routing. Si può spiegare perché alcune delle decisioni descritte in quel documento sono necessarie?
## Compito
[Migliorare l'instradamento](assignment.it.md)

View File

@@ -1,304 +0,0 @@
# バンキングアプリを作ろう その 1: Web アプリの HTML テンプレートとルート
## レッスン前の小テスト
[レッスン前の小テスト](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41?loc=ja)
### イントロダクション
ブラウザに JavaScript が登場して以来、Web サイトはこれまで以上にインタラクティブで複雑になっています。Web 技術は現在では、ブラウザに直接実行される完全に機能的なアプリケーションを作成するために一般的に使用されており、[Web アプリケーション](https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A7%E3%83%96%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)と呼ばれています。Web アプリケーションは高度にインタラクティブであるため、ユーザーはアクションが実行されるたびに全ページのリロードを待ちたくありません。そのため、JavaScript は DOM を使用して HTML を直接更新し、よりスムーズなユーザーエクスペリエンスを提供するために使用されます。
このレッスンでは、HTML テンプレートを使用して、HTML ページ全体をリロードすることなく表示・更新できる複数の画面を作成し、銀行の Web アプリを作成するための基礎を構築していきます。
### 前提条件
このレッスンで構築する Web アプリをテストするためには、ローカルの Web サーバーが必要です。もし持っていない場合は、[Node.js](https://nodejs.org/ja) をインストールして、プロジェクトフォルダから `npx lite-server` コマンドを使用してください。これでローカルの Web サーバーが作成され、ブラウザでアプリを開くことができます。
### 準備
コンピュータ上に `bank` という名前のフォルダを作成し、その中に `index.html` というファイルを作成します。この HTML [ボイラープレート](https://en.wikipedia.org/wiki/Boilerplate_code) から始めます。
```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>
<!-- ここで作業することになります。 -->
</body>
</html>
```
---
## HTML テンプレート
Web ページに複数の画面を作成したい場合、表示したい画面ごとに1つの HTML ファイルを作成するのが1つの解決策です。しかし、この方法にはいくつかの不都合があります。
- 画面切り替えの際に HTML 全体を再読み込みしなければならず、時間がかかることがあります
- 画面間でデータを共有するのは難しいです
もう一つのアプローチは、HTML ファイルを一つだけ持ち、`<template>` 要素を使って複数の [HTML テンプレート](https://developer.mozilla.org/ja/docs/Web/HTML/Element/template)を定義することです。テンプレートはブラウザに表示されない再利用可能な HTML ブロックであり、JavaScript を使って実行時にインスタンス化する必要があります。
### タスク
ログインページとダッシュボードの 2 つの画面を持つ銀行アプリを作成します。まず、アプリの異なる画面をインスタンス化するために使用するプレースホルダ要素を HTML の body に追加します。
```html
<div id="app">Loading...</div>
```
JavaScript での検索が容易になるように、`id` を付与しています。
> ヒント: この要素の内容が置き換えられるので、アプリの読み込み中に表示される読み込みメッセージやインジケータを入れることができます。
次に、ログインページの HTML テンプレートを下に追加します。今のところ、私たちはそこにタイトルとナビゲーションを実行するために使用するリンクを含むセクションを置くだけです。
```html
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
```
次に、ダッシュボードページ用に別の HTML テンプレートを追加します。このページには異なるセクションが含まれます。
- タイトルとログアウトリンクのあるヘッダー
- 銀行口座の当座預金残高
- 表に表示されるトランザクションのリスト
```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...` と表示されて動かなくなるのがわかるでしょう。これは、HTML テンプレートをインスタンス化して表示するために JavaScript コードを追加する必要があるためです。
テンプレートのインスタンス化は通常3つのステップで行われます。
1. 例えば、[`document.getElementById`](https://developer.mozilla.org/ja/docs/Web/API/Document/getElementById) を使用して、DOM 内のテンプレート要素を取得します
2. [`cloneNode`](https://developer.mozilla.org/ja/docs/Web/API/Node/cloneNode) を使用して、テンプレート要素のクローンを作成します
3. 例えば [`appendChild`](https://developer.mozilla.org/ja/docs/Web/API/Node/appendChild) を使用して、可視要素の下の DOM にアタッチします
✅ なぜ DOM にアタッチする前にテンプレートをクローンする必要があるのでしょうか? このステップをスキップしたらどうなると思いますか?
### タスク
プロジェクトフォルダに `app.js` という名前の新しいファイルを作成し、そのファイルを HTML の `<head>` セクションにインポートします。
```html
<script src="app.js" defer></script>
```
では、`app.js` で新しい関数 `updateRoute` を作成します。
```js
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つのステップとまったく同じです。テンプレートを `templateId` という名前でインスタンス化し、そのクローンされたコンテンツをアプリのプレースホルダ内に配置します。テンプレートのサブツリー全体をコピーするには、`cloneNode(true)` を使用する必要があることに注意してください。
テンプレートのサブツリー全体をコピーするには、`cloneNode(true)` を使用する必要があることに注意してください。
```js
updateRoute('login');
```
✅ このコード `app.innerHTML = '';` の目的は何ですか?これがないとどうなるのでしょうか?
## ルートの作成
Web アプリの話をするときに、**URL** を表示すべき特定の画面にマッピングする意図を *ルーティング* と呼んでいます。複数の HTML ファイルを持つ Web サイトでは、ファイルパスが URL に反映されるため、これは自動的に行われます。たとえば、プロジェクトフォルダにこれらのファイルがあるとします。
```
mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html
```
ルートに `mywebsite` を指定して Web サーバを作成した場合、URL のマッピングは以下のようになる。
```
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
```
しかし、私たちの Web アプリでは、すべての画面を含む単一の HTML ファイルを使用しているので、このデフォルトの動作は役に立ちません。この map を手動で作成し、JavaScript を使用して表示されるテンプレートの更新を実行する必要があります。
### タスク
URL パスとテンプレート間の [map](https://en.wikipedia.org/wiki/Associative_array) を実装するために、シンプルなオブジェクトを使用します。このオブジェクトを `app.js` ファイルの先頭に追加します。
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
では、`updateRoute` 関数を少し修正してみましょう。引数に `templateId` を直接渡すのではなく、まず現在の URL を見て、map を使って対応するテンプレート ID の値を取得したいと思います。URL からパス部分だけを取得するには、[`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname)を使うことができます。
```js
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 を手動で変更することなく、ページ間を移動する可能性を追加することです。これは2つのことを意味します。
1. 現在の URL を更新する
2. 新しい URL に基づいて表示されるテンプレートを更新する
2番目の部分はすでに `updateRoute` 関数で処理したので、現在の URL を更新する方法を見つけなければなりません。
JavaScript、特に [`history.pushState`](https://developer.mozilla.org/ja/docs/Web/API/History/pushState) を使う必要があります。これは HTML をリロードせずに URL を更新して閲覧履歴に新しいエントリを作成することができます。
> 注: HTML アンカー要素[`<a href>`](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a)は単独で使用して異なる URL へのハイパーリンクを作成することができますが、ブラウザはデフォルトで HTML をリロードさせることになります。カスタム javascript でルーティングを扱う際には、クリックイベントの preventDefault() 関数を使用して、この動作を防ぐ必要があります。
### タスク
アプリ内でナビゲートするために使用できる新しい関数を作成してみましょう。
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
このメソッドは最初に与えられたパスに基づいて現在の URL を更新し、その後テンプレートを更新します。プロパティ `window.location.origin` は URL のルートを返すので、与えられたパスから完全な URL を再構築することができます。
これでこの関数ができたので、パスが定義されたルートにマッチしない場合の問題を解決することができます。一致するルートが見つからなかった場合は、既存のルートにフォールバックを追加して `updateRoute` 関数を修正する。
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
ルートが見つからない場合は、`login` ページにリダイレクトします。
リンクがクリックされたときに URL を取得し、ブラウザのデフォルトのリンク動作を防ぐための関数を作ってみましょう。
```js
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
```
HTML の *Login**Logout* リンクにバインディングを追加してナビゲーションシステムを完成させましょう。
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
[`onclick`](https://developer.mozilla.org/ja/docs/Web/API/GlobalEventHandlers/onclick) 属性を使用して、`click` イベントを JavaScript コードにバインドし、ここでは `navigate()` 関数の呼び出しを行います。
これらのリンクをクリックしてみると、アプリの異なる画面間を移動できるようになるはずです。
`history.pushState` メソッドは HTML5 標準の一部であり、[すべての最新ブラウザ](https://caniuse.com/?search=pushState)で実装されています。古いブラウザ用の Web アプリを構築している場合、この API の代わりに使用できるトリックがあります。パスの前に[ハッシュ (`#`)](https://en.wikipedia.org/wiki/URI_fragment) を使用すると、通常のアンカーナビゲーションで動作し、ページを再読み込みしないルーティングを実装することができます。その目的は、ページ内に内部リンクを作成することです。
## ブラウザの戻るボタンと進むボタンの扱い
`history.pushState` を使うと、ブラウザのナビゲーション履歴に新しいエントリが作成されます。ブラウザの *戻るボタン* を押すと、以下のように表示されることを確認することができます。
![ナビゲーション履歴のスクリーンショット](../history.png)
何度か戻るボタンをクリックしてみると、現在の URL が変わって履歴が更新されていますが、同じテンプレートが表示され続けています。
これは、履歴が変わるたびに `updateRoute()` を呼び出す必要があることを知らないからです。[`history.pushState` のドキュメント](https://developer.mozilla.org/ja/docs/Web/API/History/pushState)を見てみると、状態が変化した場合、つまり別の URL に移動した場合には、[`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event)イベントが発生することがわかります。これを使ってこの問題を解決しましょう。
### タスク
ブラウザの履歴が変更されたときに表示されるテンプレートが更新されるようにするために、`updateRoute()` を呼び出す新しい関数をアタッチします。これは `app.js` ファイルの下部で行います。
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> 注: ここでは簡潔さのために `popstate` イベントハンドラを宣言するために [アロー関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions) を使用していますが、通常の関数でも同じように動作します。
これは、アロー関数についてのリフレッシュビデオです。
[![Arrow Functions](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Arrow Functions")
今度はブラウザの戻るボタンと進むボタンを使ってみて、今回表示されたルートが正しく更新されているかどうかを確認してみてください。
---
## 🚀 チャレンジ
このアプリのクレジットを表示する3ページ目のテンプレートとルートを追加します。
## レッスン後の小テスト
[レッスン後の小テスト](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42?loc=ja)
## 復習と自己学習
ルーティングは Web 開発の驚くほどトリッキーな部分の1つで、特に Web がページ更新の動作からシングルページアプリケーションのページ更新へと移行するにつれ、そのような部分が増えてきています。[Azure Static Web Apps プレビューでのルート](https://docs.microsoft.com/ja-jp/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon)がルーティングを扱うことについて少し読んでみてください。そのドキュメントに記載されているいくつかの決定が必要な理由を説明できますか?
## 課題
[ルーティングの改善](assignment.ja.md)

View File

@@ -1,295 +0,0 @@
# 은행 앱 제작하기 파트 1: 웹 앱의 HTML 템플릿과 라우터
## 강의 전 퀴즈
[Pre-lecture quiz](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41?loc=ko)
### 소개
브라우저에 JavaScript가 등장한 이후, 웹 사이트는 그 어느 순간보다 상호 작용하며 복잡해지고 있습니다. 웹 기술은 일반적으로 [web applications](https://en.wikipedia.org/wiki/Web_application)라고 불리는 브라우저로 직접 실행되는 완전한 기능의 애플리케이션을 만들 때 사용됩니다. 웹 앱은 매우 대화형이므로, 사용자는 작업되는 순간에 전체 페이지가 다시 불러오며 기다리는 것을 원치 않습니다. 원활한 사용자 경험을 제공하기 위해, JavaScript로 DOM을 사용하여 HTML을 직접 갱신합니다.
이번 강의에서는, 전체 HTML 페이지를 다시 불러오지 않으면서 출력하고 갱신할 여러 화면을 만들기 위해 HTML 템플릿을 사용할 것이므로, 은행 웹 앱을 만들기 위한 기초를 레이아웃합니다.
### 준비물
이 강의에서 만들 웹 앱을 테스트하려면 로컬 웹 서버가 필요합니다. 없는 경우에는, [Node.js](https://nodejs.org)를 설치하고 프로젝트 폴더에서 `npx lite-server` 명령을 수행할 수 있습니다. 로컬 웹 서버를 만들고 브라우저에서 앱을 엽니다.
### 준비
컴퓨터에서, `index.html` 파일이 있는 `bank`라는 폴더를 만듭니다. 이 HTML [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code)에서 시작할 것 입니다.
```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 파일이 하나일 때, `<template>` 요소로 여러 [HTML templates](https://developer.mozilla.org/docs/Web/HTML/Element/template)을 정의하는 것입니다. 템플릿은 브라우저에 보이지 않는 재사용 가능한 HTML 블록이면서, JavaScript를 사용해서 런타임에 인스턴스화합니다.
### 작업
두 화면이 있는 은행 앱을 만들 것입니다: 로그인 페이지와 대시보드. 먼저, 앱의 다양한 화면을 인스턴스화할 때 사용할 placeholder 요소를 HTML 본문에 추가하겠습니다:
```html
<div id="app">Loading...</div>
```
나중에 JavaScript로 쉽게 찾도록 `id`를 제공합니다.
> Tip: 이 요소의 내용은 바뀌므로, 앱이 불러와지는 동안 보여지는 로딩 메시지 또는 인디케이터를 넣을 수 있습니다.
다음은, 로그인 페이지 HTML 템플릿 아래에 추가하겠습니다. 지금은 탐색하며 사용할 버튼이 포함된 제목과 섹션만 여기에 넣겠습니다.
```html
<template id="login">
<h1>Bank App</h1>
<section>
<button>Login</button>
</section>
</template>
```
그러고 대시보드 페이지에 대한 다른 HTML 템플릿을 추가합니다. 이 페이지에는 다른 섹션도 포함됩니다:
- 제목과 로그아웃 버튼이 있는 헤더
- 은행 계정의 현재 잔액
- 테이블에 표시된, 트랜잭션 목록
```html
<template id="dashboard">
<header>
<h1>Bank App</h1>
<button>Logout</button>
</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>
```
> Tip: HTML 템플릿을 만들 때, 모양을 확인하려면, `<!-->`로 묶어 `<template>` 혹은 `</template>` 줄을 주석 처리할 수 있습니다.
✅ 템플릿에 `id` 속성을 사용하는 이유는 무엇일까요? 강의처럼 다른 것을 쓸 수 있나요?
## JavaScript로 템플릿 출력하기
브라우저에서 현재 HTML 파일을 시도하면, `Loading...`이 출력되는 것을 볼 수 있습니다. HTML 템플릿을 인스턴스화하고 출력하기 위해 JavaScript 코드를 추가했기 때문입니다.
템플릿 인스턴스화는 일반적으로 3 단계로 진행됩니다:
1. [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById)를 사용한 예시로, DOM에서 템플릿 요소 검색합니다.
2. [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode)로, 템플릿 요소를 복제합니다.
3. [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild)를 사용한 예시로, 보이는 요소 아래의 DOM에 붙입니다.
✅ DOM에 붙이기 전에 템플릿을 복제해야하는 이유는 무엇일까요? 이 단계를 넘기면 어떻게 될까요?
### 작업
프로젝트 폴더에 `app.js`라는 새 파일을 만들고 HTML의 `<head>` 섹션에서 해당 파일을 가져옵니다:
```html
<script src="app.js" defer></script>
```
이제 `app.js`에서, 새로운 함수인 `updateRoute`를 만듭니다:
```js
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`로 템플릿을 인스턴스화하고, 복제된 콘텐츠를 앱 placeholder에 넣습니다. 템플릿의 전체 하위 트리를 복사하려면 `cloneNode(true)`로 사용해야 합니다.
이제 템플릿 중 하나를 사용하여 이 함수를 호출하고 결과를 봅니다.
```js
updateRoute('login');
```
✅ 이 `app.innerHTML = '';` 코드의 목적은 무엇인가요? 없다면 어떻게 될까요?
## 라우터 생성하기
웹 앱에 대해 이야기할 때, **URLs**을 보여주기 위해 특정 화면에 매핑하려는 의도를 *Routing*이라고 합니다. 여러 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 경로와 템플릿 사이에서 [map](https://en.wikipedia.org/wiki/Associative_array)을 구현합니다. `app.js` 파일의 상단에 객체를 추가합니다.
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
이제 `updateRoute` 함수를 약간 수정합니다. `templateId`를 인수로 직접 주는 대신, 먼저 현재 URL을 보고 찾은 다음, 맵을 사용하여 해당 템플릿 ID 값을 가져오려 합니다. [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname)으로 URL에서 경로 섹션만 가져올 수 있습니다.
```js
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로 갱신하는 방법을 알아냅니다.
HTML 앵커 요소 [`<a>`](https://developer.mozilla.org/docs/Web/HTML/Element/a)를 사용하여 다른 URL에 대한 하이퍼링크를 만들 수 있지만, 여기에서 사용하면 브라우저가 HTML을 다시 불러오게 됩니다.
대신 URL을 업데이트 할 수 있는 JavaScript와 더 구체적으로 [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState)를 사용해야합니다. HTML을 다시 불러오지 않고 검색 기록에 새로운 항목을 만듭니다.
### 작업
앱에서 탐색할 때 사용할 수 있는 새로운 함수를 만들어 보겠습니다:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
이 메소드는 먼저 주어진 경로에 따라 현재 URL을 갱신한 다음에, 템플릿을 업데이트합니다. `window.location.origin` 속성은 URL 최상위를 반환하므로, 주어진 경로에서 전체 URL을 다시 구성할 수 있습니다.
이제 함수가 있으므로, 경로가 정의된 라우터와 일치하지 않는 경우에 발생할 문제를 해결할 수 있습니다. 일치하는 경로를 찾을 수 없는 경우에는 기존 경로 중 하나에 fallback로 추가하고자 `updateRoute` 함수를 수정합니다.
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
만약 라우터를 찾지 못한다면, `login` 페이지로 리다이렉트됩니다.
HTML의 *Login*과 *Logout* 버튼에 바인딩을 추가하여 내비게이션 시스템을 완성해봅니다.
```html
<button onclick="navigate('/dashboard')">Login</button>
...
<button onclick="navigate('/login')">Logout</button>
```
[`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) 속성을 사용하여 `click` 이벤트를 JavaScript 코드로 바인딩합니다, 여기에서 `navigate()` 함수를 호출합니다.
이 버튼들을 클릭해보세요, 이제 앱의 여러 화면들을 이동할 수 있습니다.
`history.pushState` 메소드는 HTML5 표준의 일부이며 [모든 모던 브라우저](https://caniuse.com/?search=pushState)에서 구현됩니다. 옛날 브라우저의 웹 앱을 제작하는 경우, 이 API 대신 사용할 수 있는 트릭이 있습니다: 경로 앞에 [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment)를 사용한다면 일반 앵커 탐색처럼 동작하면서 페이지를 다시 안 불러오는 라우팅을 구현할 수 있습니다, 페이지 내에 내부 링크를 만드는 것이 목적입니다.
## 브라우저의 뒤로가기와 앞으로가기 버튼 제어하기
`history.pushState`를 사용하면 브라우저의 탐색 기록에 새로운 항목이 생성됩니다. 브라우저의 *back button*을 누르고 있으면 다음처럼 내용이 표시되는지 볼 수 있습니다:
![Screenshot of navigation history](.././history.png)
뒤로가기 버튼을 몇 번 클릭하면, 현재 URL이 변경되며 히스토리가 갱신되지만 동일한 템플릿이 계속 출력되는 것을 볼 수 있습니다.
히스토리가 바뀔 때마다 `updateRoute()`를 호출해야 한다는 사실을 모르기 때문입니다. [`history.pushState` documentation](https://developer.mozilla.org/docs/Web/API/History/pushState)을 살펴보면, 상태가 바뀌는 지 확인할 수 있습니다 - 다른 URL로 이동했다고 의미합니다. - [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) 이벤트가 연결됩니다. 이 이슈를 해결하는 데 사용할 것입니다.
### 작업
브라우저 히스토리가 바뀔 때마다 출력된 템플릿을 갱신하도록 `updateRoute()`를 호출하는 새 함수를 붙입니다. `app.js` 파일 하단에서 작업합니다:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> Note: 여기서는 간결함을 위해 [arrow function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions)을 사용하여 `popstate` 이벤트 핸들러를 선언했지만, 일반적인 함수와 동일하게 작동합니다.
다음은 화살표 함수에 대한 복습 동영상입니다:
[![Arrow Functions](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Arrow Functions")
이제 브라우저의 뒤로가기와 앞으로가기 버튼을 사용해보세요, 그리고 이 순간마다 올바르게 갱신되어 출력되는 지에 대하여 확인합니다.
---
## 🚀 도전
이 앱의 크레딧을 보여주는 세 번째 페이지에 새로운 템플릿과 라우터를 추가합니다.
## 강의 후 퀴즈
[Post-lecture quiz](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42?loc=ko)
## 리뷰 & 자기주도 학습
라우팅은 웹 개발의 놀랍고 까다로운 부분 중 하나입니다, 특히 웹의 페이지 새로고침 동작에서 단일 페이지 애플리케이션 페이지 새로고침으로 이동함에 따라 더욱 더 그렇습니다. [how the Azure Static Web App service](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon)의 라우터 제어에 대해 약간 봅니다. 그 문서에 기술된 몇 가지 결정이 필요한 이유를 설명할 수 있나요?
## 과제
[Improve the routing](../assignment.md)

View File

@@ -1,306 +0,0 @@
# Bina Aplikasi Perbankan Bahagian 1: Templat dan Laluan HTML dalam Aplikasi Web
## Kuiz Pra Kuliah
[Kuiz Pra Kuliah](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41)
### Arahan
Sejak munculnya JavaScript di penyemak imbas, laman web menjadi lebih interaktif dan kompleks daripada sebelumnya. Teknologi web kini biasa digunakan untuk membuat aplikasi berfungsi sepenuhnya yang langsung masuk ke penyemak imbas yang kita panggil [aplikasi web](https://en.wikipedia.org/wiki/Web_application). Oleh kerana aplikasi Web sangat interaktif, pengguna tidak mahu menunggu muat semula halaman penuh setiap kali tindakan dilakukan. Itulah sebabnya JavaScript digunakan untuk mengemas kini HTML secara langsung menggunakan DOM, untuk memberikan pengalaman pengguna yang lebih lancar.
Dalam pelajaran ini, kita akan meletakkan dasar untuk membuat aplikasi web bank, menggunakan templat HTML untuk membuat banyak layar yang dapat ditampilkan dan diperbarui tanpa harus memuat ulang seluruh halaman HTML.
### Prasyarat
Anda memerlukan pelayan web tempatan untuk menguji aplikasi web yang akan kami bina dalam pelajaran ini. Sekiranya tidak memilikinya, anda boleh memasang [Node.js](https://nodejs.org) dan menggunakan arahan `npx lite-server` dari folder projek anda. Ini akan membuat pelayan web tempatan dan membuka aplikasi anda di penyemak imbas.
### Penyediaan
Di komputer anda, buat folder bernama `bank` dengan fail bernama `index.html` di dalamnya. Kami akan bermula dari HTML [boilerplate](https://en.wikipedia.org/wiki/Boilerplate_code):
```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>
```
---
## Templat HTML
Jika anda ingin membuat beberapa layar untuk halaman web, satu penyelesaiannya adalah dengan membuat satu file HTML untuk setiap layar yang ingin anda tampilkan. Walau bagaimanapun, penyelesaian ini disertakan dengan beberapa kesulitan:
- Anda harus memuat semula keseluruhan HTML ketika menukar skrin, yang boleh menjadi lambat.
- Sukar untuk berkongsi data antara skrin yang berbeza.
Pendekatan lain hanya mempunyai satu fail HTML, dan menentukan beberapa [templat HTML](https://developer.mozilla.org/docs/Web/HTML/Element/template) menggunakan elemen `<template>`. Templat adalah blok HTML yang dapat digunakan kembali yang tidak ditampilkan oleh penyemak imbas, dan perlu dibuat pada waktu berjalan menggunakan JavaScript.
### Tugas
Kami akan membuat aplikasi bank dengan dua skrin: halaman log masuk dan papan pemuka. Pertama, mari kita tambahkan elemen penanda tempat pada badan HTML yang akan kita gunakan untuk menunjukkan pelbagai skrin aplikasi kita:
```html
<div id="app">Loading...</div>
```
Kami memberikannya `id` untuk memudahkan pencarian dengan JavaScript kemudian.
> Petua: kerana kandungan elemen ini akan diganti, kita dapat memasukkan pesan pemuatan atau penunjuk yang akan ditunjukkan semasa aplikasi dimuat.
Seterusnya, mari kita tambahkan di bawah templat HTML untuk halaman log masuk. Buat masa ini kami hanya akan memasukkan tajuk dan bahagian yang mengandungi pautan yang akan kami gunakan untuk melakukan navigasi.
```html
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
```
Kemudian kami akan menambahkan templat HTML lain untuk halaman papan pemuka. Halaman ini akan mengandungi bahagian yang berbeza:
- Tajuk dengan tajuk dan pautan log keluar
- Baki semasa akaun bank
- Senarai urus niaga, ditunjukkan dalam jadual
```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>
```
> Petua: semasa membuat templat HTML, jika anda ingin melihat seperti apa, anda boleh memberi komen baris `<template>` `dan` `</template>` dengan melampirkannya dengan `<! - -> ` .
✅ Menurut anda mengapa kami menggunakan atribut `id` pada templat? Bolehkah kita menggunakan sesuatu yang lain seperti kelas?
## Memaparkan templat dengan JavaScript
Sekiranya anda mencuba fail HTML semasa anda dalam penyemak imbas, anda akan melihat fail tersebut macet memaparkan `Memuat ... '. Itu kerana kita perlu menambahkan beberapa kod JavaScript untuk memberi contoh dan memaparkan templat HTML.
Membuat templat biasanya dilakukan dalam 3 langkah:
1. Dapatkan semula elemen templat di DOM, misalnya menggunakan [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Klon elemen templat, menggunakan [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
3. Lampirkan ke DOM di bawah elemen yang kelihatan, misalnya menggunakan [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild).
✅ Mengapa kita perlu mengklon templat sebelum melampirkannya ke DOM? Apa yang anda fikir akan berlaku sekiranya kita melangkau langkah ini?
### Tugas
Buat fail baru bernama `app.js` di folder projek anda dan import fail itu di bahagian `<head>` HTML anda:
```html
<script src="app.js" defer></script>
```
Sekarang di `app.js`, kami akan membuat fungsi baru `updateRoute`:
```js
function updateRoute(templateId) {
const template = document.getElementById(templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
```
Apa yang kami lakukan di sini adalah tepat 3 langkah yang dinyatakan di atas. Kami membuat templat dengan id `templateId`, dan memasukkan kandungan klonnya ke dalam ruang letak aplikasi kami. Perhatikan bahawa kita perlu menggunakan `cloneNode(true)` untuk menyalin keseluruhan subtree templat.
Sekarang panggil fungsi ini dengan salah satu templat dan lihat hasilnya.
```js
updateRoute('login');
```
✅ Apa tujuan kod ini `app.innerHTML = '';`? Apa yang berlaku tanpanya?
## Membuat laluan
Ketika berbicara tentang aplikasi web, kami memanggil *Routing* niat untuk memetakan **URL** ke layar tertentu yang harus ditampilkan. Di laman web dengan banyak fail HTML, ini dilakukan secara automatik kerana jalur fail ditunjukkan pada URL. Contohnya, dengan fail ini dalam folder projek anda:
```
mywebsite/index.html
mywebsite/login.html
mywebsite/admin/index.html
```
Sekiranya anda membuat pelayan web dengan `mywebsite` sebagai root, pemetaan URL akan:
```
https://site.com --> mywebsite/index.html
https://site.com/login.html --> mywebsite/login.html
https://site.com/admin/ --> mywebsite/admin/index.html
```
Walau bagaimanapun, untuk aplikasi web kami menggunakan satu fail HTML yang mengandungi semua skrin sehingga tingkah laku lalai ini tidak akan membantu kami. Kita harus membuat peta ini secara manual dan melakukan kemas kini templat yang dipaparkan menggunakan JavaScript.
### Tugas
Kami akan menggunakan objek sederhana untuk melaksanakan [peta](https://en.wikipedia.org/wiki/Associative_array) antara jalur URL dan templat kami. Tambahkan objek ini di bahagian atas fail `app.js` anda.
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
Sekarang mari kita ubah sedikit fungsi `updateRoute`. Daripada meneruskan secara langsung `templateId` sebagai argumen, kami ingin mendapatkannya dengan terlebih dahulu melihat URL semasa, dan kemudian menggunakan peta kami untuk mendapatkan nilai ID templat yang sesuai. Kita boleh menggunakan [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) untuk mendapatkan hanya bahagian jalan dari URL.
```js
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);
}
```
Di sini kami memetakan laluan yang kami nyatakan ke templat yang sesuai. Anda boleh mencubanya agar berfungsi dengan betul dengan menukar URL secara manual di penyemak imbas anda.
✅ Apa yang berlaku jika anda memasukkan jalan yang tidak diketahui dalam URL? Bagaimana kita dapat menyelesaikannya?
## Tambahkan navigasi
Langkah seterusnya untuk aplikasi kita adalah menambahkan kemungkinan untuk menavigasi antara halaman tanpa perlu mengubah URL secara manual. Ini menunjukkan dua perkara:
1. Mengemas kini URL semasa
2. Mengemas kini templat yang dipaparkan berdasarkan URL baru
Kami sudah mengurus bahagian kedua dengan fungsi `updateRoute`, jadi kami harus memikirkan cara mengemas kini URL semasa.
Kita mesti menggunakan JavaScript dan lebih khusus lagi [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) yang memungkinkan untuk mengemas kini URL dan buat entri baru dalam sejarah penyemakan imbas, tanpa memuatkan semula HTML.
> Catatan: Walaupun elemen anchor HTML [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) dapat digunakan sendiri untuk membuat hyperlink ke URL yang berbeza, ini akan menjadikan penyemak imbas memuat semula HTML secara lalai. Adalah perlu untuk mencegah tingkah laku ini ketika menangani routing dengan javascript khusus, menggunakan fungsi preventDefault () pada peristiwa klik.
### Tugas
Mari buat fungsi baru yang dapat kita gunakan untuk menavigasi di aplikasi kita:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
Kaedah ini terlebih dahulu mengemas kini URL semasa berdasarkan jalan yang diberikan, kemudian mengemas kini templat. Properti `window.location.origin` mengembalikan akar URL, yang membolehkan kami membina semula URL lengkap dari jalan yang ditentukan.
Sekarang kita mempunyai fungsi ini, kita dapat mengatasi masalah yang kita ada jika jalan tidak sesuai dengan rute yang ditentukan. Kami akan mengubah fungsi `updateRoute` dengan menambahkan fallback ke salah satu laluan yang ada jika kami tidak dapat mencari yang sesuai.
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
Sekiranya laluan tidak dapat dijumpai, kami sekarang akan mengalihkan ke halaman `login`.
Sekarang mari kita buat fungsi untuk mendapatkan URL apabila pautan diklik, dan untuk mengelakkan tingkah laku pautan lalai penyemak imbas:
```js
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
```
Mari lengkapkan sistem navigasi dengan menambahkan pengikatan pada pautan *Login* dan *Logout* kami dalam HTML.
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
Menggunakan atribut [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) mengikat peristiwa`klik` ke kod JavaScript, di sini panggilan ke `navigasi() `fungsi.
Cuba klik pada pautan-pautan ini, kini anda seharusnya dapat menavigasi antara pelbagai skrin aplikasi anda.
✅ Kaedah `history.pushState` adalah sebahagian daripada standard HTML5 dan dilaksanakan di [semua penyemak imbas moden](https://caniuse.com/?search=pushState). Sekiranya anda membuat aplikasi web untuk penyemak imbas yang lebih lama, ada helah yang dapat Anda gunakan sebagai ganti API ini: menggunakan [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) sebelum jalan yang dapat anda laksanakan perutean yang berfungsi dengan navigasi jangkar biasa dan tidak memuat semula halaman, kerana tujuannya adalah untuk membuat pautan dalaman dalam halaman.
## Mengendalikan butang belakang dan hadapan penyemak imbas
Menggunakan `history.pushState` membuat entri baru dalam sejarah navigasi penyemak imbas. Anda boleh memastikan bahawa dengan menahan * butang belakang * penyemak imbas anda, ia akan memaparkan sesuatu seperti ini:
![Tangkapan skrin sejarah navigasi](../history.png)
Sekiranya anda cuba mengklik butang kembali beberapa kali, anda akan melihat bahawa URL semasa berubah dan sejarahnya dikemas kini, tetapi templat yang sama terus dipaparkan.
Ini kerana tidak tahu bahawa kita perlu memanggil `updateRoute()` setiap kali sejarah berubah. Sekiranya anda melihat dokumentasi [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), anda dapat melihat bahawa jika keadaan berubah - yang bermaksud bahawa kami berpindah ke URL yang berbeza - peristiwa [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) dicetuskan. Kami akan menggunakannya untuk menyelesaikan masalah itu.
### Tugas
Untuk memastikan templat yang ditampilkan diperbaharui ketika sejarah penyemak imbas berubah, kami akan melampirkan fungsi baru yang memanggil `updateRoute ()`. Kami akan melakukannya di bahagian bawah fail `app.js` kami:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> Catatan: kami menggunakan [fungsi panah](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) di sini untuk menyatakan pengendali acara `popstate` kami untuk kesimpulan, fungsi biasa akan berfungsi sama.
Berikut adalah video penyegaran mengenai fungsi anak panah:
[![Fungsi Anak Panah](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "Fungsi Anak Panah")
> Klik gambar di atas untuk video mengenai fungsi anak panah.
Sekarang cuba gunakan butang belakang dan depan penyemak imbas anda, dan periksa bahawa laluan yang dipaparkan dikemas kini dengan betul kali ini.
---
## 🚀 Cabaran
Tambahkan templat dan laluan baru untuk halaman ketiga yang menunjukkan kredit untuk aplikasi ini.
## Kuiz Pasca Kuliah
[Kuiz Pasca Kuliah](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42)
## Mengkaji & Belajar Sendiri
Perutean adalah salah satu bahagian pengembangan web yang sangat mengejutkan, terutama ketika web beralih dari tingkah laku penyegaran halaman ke penyegaran halaman Aplikasi Halaman Tunggal. Baca sedikit mengenai [bagaimana perkhidmatan Aplikasi Web Statik Azure](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon) menangani penghalaan . Bolehkah anda menjelaskan mengapa beberapa keputusan yang dijelaskan pada dokumen itu diperlukan?
## Tugasan
[Tingkatkan penghalaan](assignment.ms.md)

View File

@@ -1,307 +0,0 @@
# 建立銀行網頁應用程式 Part 1HTML 模板與網頁路由
## 課前測驗
[課前測驗](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/41?loc=zh_tw)
### 大綱
自從 JavaScript 出現在瀏覽器後,網頁開始變得更複雜、更多互動。網頁技術已經普遍地用於建立功能齊全的應用程式,執行在瀏覽器上,我們稱之為[網頁應用程式](https://zh.wikipedia.org/zh-tw/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F)。基於網頁應用程式的高互動性,使用者不會想在互動後做所有頁面載入所需的等待。這也是為什麼 JavaScript 使用 DOM 來更新 HTML提供使用者更流暢的網頁體驗。
在這堂課程中,我們會譜出銀行網頁應用程式的基礎,使用 HTML 模板建立不同的畫面,各自顯示並更新內容,而不必每次都需要載入整個 HTML 頁面。
### 開始之前
你需要一個網頁伺服器來測試我們要建的專案。如果你還沒有,你可以安裝 [Node.js](https://nodejs.org) 並在你的專案資料夾中使用指令 `npx lite-server`。這會建立一個本地端的網頁伺服器,在瀏覽器上開啟你的網頁程式。
### 準備
在你的電腦上,建立資料夾 `bank`,並在裡面建立檔案 `index.html`。我們以這個 HTML [樣板](https://en.wikipedia.org/wiki/Boilerplate_code)來開始:
```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 模板(templates)
如果你想在同一個網頁上建立不同的畫面,其中一種方法是各自建立一個 HTML 檔給每一個你想呈現的子畫面。然而,這個方式有許多不便之處:
- 你需要在切換頁面時,重新載入整個網頁。這會很花時間。
- 在不同子頁面上共享數據會是一大難題。
另一個解決方案是只有一個 HTML 檔案,並使用 `<template>` 元素定義多個 [HTML 模板](https://developer.mozilla.org/docs/Web/HTML/Element/template)。
一個模板提供可重複利用的 HTML 區塊,它不會顯示在瀏覽器上,而在需要之時由 JavaScript 以呈現出來。
### 課題
我們會建立一個銀行網頁應用程式,其中包含兩個子畫面:登入頁面與儀表板頁面。首先,我們在網頁應用程式的 HTML body 上,建立放置區來放置模板的子頁面。
```html
<div id="app">Loading...</div>
```
我們給它 `id`,以利後續 JavaScript 對它的追蹤。
> 提示:因為它裡面元素的內容會被置換,我們可以建立載入中訊息或提示,在應用程式載入時顯示出來。
接下來,我們加入下列的 HTML 模板,給登入畫面使用。現在我們只加入一行標題與一個有連結的區塊,進行簡單的功能。
```html
<template id="login">
<h1>Bank App</h1>
<section>
<a href="/dashboard">Login</a>
</section>
</template>
```
接著,加入另一個 HTML 模板給儀表板頁面。這個頁面就會包含不同的區塊:
- 包含標題與登出連結的網頁標頭
- 現在的銀行帳戶餘額
- 一個歷史交易清單的表格
```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` 屬性嗎?我們可以使用別的屬性,例如 classes 嗎?
## 利用 JavaScript 顯示模板
現在,如果你使用瀏覽器打開你的應用程式,你會看到畫面卡在 `Loading...` 的畫面。那是因為我們需要為它新增一些 JavaScript 的程式碼來顯示出這些 HTML 模板。
展現模板通常需要三個步驟:
1. 在 DOM 內接收模板元素,舉例來說,使用 [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById)。
2. 複製模板元素,使用 [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode)。
3. 將複製元素接到 DOM 的顯示元素上,例如使用 [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild)。
✅ 我們為什麼需要在接到 DOM 前,複製一份模板?你能想像如果我們省略了此步驟後,會發生什麼事嗎?
### 課題
在資料夾中建立新檔案 `app.js`,並在你的 HTML 檔案的 `<head>` 區塊中中匯入這個新檔案:
```html
<script src="app.js" defer></script>
```
`app.js` 中,我們建立新函式 `updateRoute`
```js
function updateRoute(templateId) {
const template = document.getElementById(templateId);
const view = template.content.cloneNode(true);
const app = document.getElementById('app');
app.innerHTML = '';
app.appendChild(view);
}
```
這裡做的事情就是我們上述提及過的三個步驟。我們使用 `templateId` 展現了模板,並將複製的內容接在我們的放置區中。注意我們需要使用 `cloneNode(true)` 來複製整個模板的子樹。
現在我們呼叫這個函式,指定特定的模板並觀察結果。
```js
updateRoute('login');
```
✅ 程式碼中 `app.innerHTML = '';` 的目的為何?如果刪去它會發生什麼事?
## 建立網頁路由(Routing)
當提及網頁應用程式時,我們稱呼 *路由(Routing)* 來連接**網址(URLs)**到特定的畫面上,呈現相關內容。一個含有多個 HTML 檔的網頁,網址又象徵著檔案路徑,這能自動地完成網址與檔案的轉換。舉例來說,專案資料夾內有這些檔案:
```
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 網址與模板的[關聯實體關係](https://en.wikipedia.org/wiki/Associative_array)。加入這個物件到 `app.js` 檔案的最上方。
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
現在,我們對函式 `updateRoute` 做一些更動。我們不直接將 `templateId` 作為參數傳遞,而是接收現在的 URL 網址,在使用關聯表來取得相對應的模板 ID 數值。我們可以使用 [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) 來取得網址的部分路徑。
```js
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);
}
```
這邊我們建立了模板的路由關係。你可以藉由修改網址,來測試你的網頁是否正確的轉移。
✅ 如果你輸入了不存在的網址,它會發生什麼事?我們該如何解決呢?
## 加入網頁訪問
下一個步驟為在不更改網址的情況下,新增網頁訪問的途徑。這會做出兩件事情:
1. 更新現在的網址
2. 更新要被顯示的模板到新的網址中
我們已經完成了第二點,藉由使用函式 `updateRoute` 來完成,所以我們需要釐清該如何更新現在的網址。
我們需要使用 JavaScript詳細來看為 [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState),更新網址位置並建立瀏覽紀錄,同時不更新整個 HTML 頁面。
> 筆記:網頁超連結元素 [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) 可以建立不同網址的連接,但它預設上會讓瀏覽器重新載入 HTML 檔。我們需要手動新增 JavaScript 處理路由以避免此行為發生,在點擊事件中使用函式 preventDefault() 。
### 課題
我們來建立新的函式,讓應用程式得以做網頁的訪問:
```js
function navigate(path) {
window.history.pushState({}, path, path);
updateRoute();
}
```
這個方法根據導入的路徑位置,更新了現在的網址位置,再更新模板上去。`window.location.origin` 回傳了網址的根路徑,允許我們重新構築完整的網址。
現在,藉由上述的函式,我們可以解決找不到網頁路徑的問題。我們修改函式 `updateRoute`,在找不到該網頁時強制轉移到一個存在的網頁。
```js
function updateRoute() {
const path = window.location.pathname;
const route = routes[path];
if (!route) {
return navigate('/login');
}
...
```
如果找不到網頁路由時,我們會導往 `login` 的頁面。
現在,我們建立新的函式,在連結被點擊時取得網址位置,並避免瀏覽器進行預設上的重新載入:
```js
function onLinkClick(event) {
event.preventDefault();
navigate(event.target.href);
}
```
現在我們完成應用程式的網頁訪問系統,在 HTML 檔的 *Login**Logout* 連結加入此函式。
```html
<a href="/dashboard" onclick="onLinkClick(event)">Login</a>
...
<a href="/login" onclick="onLinkClick(event)">Logout</a>
```
使用 [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) 屬性會將 `click` 事件連接到 JavaScript 程式碼中,這邊會再呼叫函式 `navigate()`
試著點擊這些連結,你應該能造訪網頁中不同的的畫面了。
`history.pushState` 這個方法是 HTML5 標準的一部份,支援在[所有當代的瀏覽器](https://caniuse.com/?search=pushState)上。如果你要為舊款的瀏覽器設計網頁應用程式的話,這邊有一個技巧來加在這個 API 上:在路徑前面加上 [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment),你可以完成網頁路由與不須重載網頁的功能,它的目的就是在同一個網頁中做內部連結的切換。
## 處理瀏覽器的「上一頁」與「下一頁」
使用 `history.pushState` 會建立瀏覽器的瀏覽紀錄。你可以使用瀏覽器的*上一頁*來確認,它應該要能呈現像這樣的畫面:
![瀏覽歷史的截圖](../history.png)
點擊上一頁數次,你會看到網址會改變且歷史紀錄也更新上去了,但同一個模板還是被顯示出來。
這是因為網頁不知道該如何依據歷史紀錄來呼叫 `updateRoute()`。如果你閱讀了 [`history.pushState` 技術文件](https://developer.mozilla.org/docs/Web/API/History/pushState),你會發現如果狀態改變 ── 同時代表著網址改變 ── [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) 事件就會被觸發。我們會利用此特徵來修復這個問題。
### 課題
為了在瀏覽器歷史改變時更新該被顯示的模板,我們會以新函式來呼叫 `updateRoute()`。我們在 `app.js` 檔最下方加入:
```js
window.onpopstate = () => updateRoute();
updateRoute();
```
> 筆記:我們在這裡使用[箭頭函式](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions),簡短地宣告 `popstate` 事件處理器。它與正規的函式的功能是一樣的。
這是關於箭頭函式的回想影片:
[![箭頭函式](https://img.youtube.com/vi/OP6eEbOj2sc/0.jpg)](https://youtube.com/watch?v=OP6eEbOj2sc "箭頭函式")
> 點擊上方圖片以觀看關於箭頭函式的影片。
現在,試著點擊瀏覽器上的上一頁與下一頁,檢查這次模板是否正確地更新出來。
---
## 🚀 挑戰
加入新的模板與對應的關聯表,顯示出本應用程式第三頁的功能 ── 帳戶餘額。
## 課後測驗
[課後測驗](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/42?loc=zh_tw)
## 複習與自學
網頁路由是網頁開發中很棘手的部分,特別是將網頁切換轉變為單一頁面應用程式(Single Page Application)。閱讀關於[Azure Static Web App 提供服務的方式](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon)以處理網頁路由。你能解釋為什麼文件上的某些決定會如此重要呢?
## 作業
[增進網頁路由](assignment.zh-tw.md)

View File

@@ -1,14 +0,0 @@
# Mejorar el enrutamiento
## Instrucciones
La declaración de rutas contiene actualmente solo el ID de plantilla a usar. Pero cuando se muestra una página nueva, a veces se necesita un poco más. Mejoremos nuestra implementación de enrutamiento con dos características adicionales:
- Dé títulos a cada plantilla y actualice el título de la ventana con él cuando cambie la plantilla.
- Agregue una opción para ejecutar código después de que cambie la plantilla. Queremos imprimir `'Se muestra el panel'` en la consola del desarrollador cada vez que se muestra la página del panel.
## Rúbrica
| Criterios | Ejemplar | Adecuado | Necesita mejorar |
| -------- | --------- | -------- | ----------------- |
| | Las dos características están implementadas y funcionando. La adición de título y código también funciona para una nueva ruta agregada en la declaración de `routes`. | Las dos características funcionan, pero el comportamiento está codificado y no se puede configurar a través de la declaración de `routes`. Agregar una tercera ruta con la adición de título y código no funciona o funciona parcialmente. | Una de las funciones falta o no funciona correctamente.

View File

@@ -1,15 +0,0 @@
# Améliorer le routage
## Instructions
La déclaration de routes ne contient actuellement que l'ID de modèle à utiliser. Mais lors de l'affichage d'une nouvelle page, un peu plus que celà est parfois nécessaire. Améliorons notre implémentation de routage avec deux fonctionnalités supplémentaires :
- Donnez des titres à chaque modèle et mettez à jour le titre de la fenêtre avec ce nouveau titre lorsque le modèle change.
- Ajouter une option pour exécuter du code après les modifications du modèle. Nous voulons afficher « Le tableau de bord est affiché » dans la console du développeur à chaque fois que la page du tableau de bord est affichée.
## Rubrique
| Critères | Exemplaire | Adéquat | Besoin d'amélioration |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| | Les deux fonctionnalités sont implémentées et fonctionnent. L'ajout de titre et de code fonctionne également pour une nouvelle route ajoutée dans la déclaration `routes`. | Les deux fonctionnalités fonctionnent, mais le comportement est codé en dur et non configurable via la déclaration `routes`. L'ajout d'une troisième route avec une addition de titre et de code ne fonctionne pas ou fonctionne partiellement. | L'une des fonctionnalités est manquante ou ne fonctionne pas correctement. |

View File

@@ -1,14 +0,0 @@
# रूटिंग में सुधार करें
## अनुदेश
मार्गों की घोषणा में वर्तमान में उपयोग करने के लिए केवल टेम्पलेट आईडी है। लेकिन एक नया पृष्ठ प्रदर्शित करते समय, कभी-कभी थोड़ा और अधिक की आवश्यकता होती है। आइए दो अतिरिक्त सुविधाओं के साथ हमारे रूटिंग कार्यान्वयन में सुधार करें:
- प्रत्येक टेम्पलेट को शीर्षक दें और जब टेम्पलेट बदलता है तो इस नए शीर्षक के साथ विंडो शीर्षक को अपडेट करें।
- टेम्पलेट परिवर्तन के बाद कुछ कोड चलाने के लिए एक विकल्प जोड़ें। हम हर बार डैशबोर्ड पृष्ठ प्रदर्शित होने पर डेवलपर कंसोल में `'Dashboard is shown'` प्रिंट करना चाहते हैं
## शीर्ष
| मानदंड | उदाहरणात्मक | पर्याप्त | सुधार की जरूरत |
| ------ | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| | दो विशेषताएं कार्यान्वित और काम कर रही हैं। शीर्षक और कोड जोड़ भी `routes` घोषणा में जोड़े गए एक नए मार्ग के लिए काम करते हैं. | दो सुविधाएँ काम करती हैं, लेकिन व्यवहार कठिन है और `routes` घोषणा के माध्यम से विन्यास योग्य नहीं है। शीर्षक और कोड जोड़ के साथ तीसरा मार्ग जोड़ना आंशिक रूप से काम या काम नहीं करता है. | सुविधाओं में से एक गायब है या ठीक से काम नहीं कर रहा है. |

View File

@@ -1,14 +0,0 @@
# Migliorare l'instradamento
## Istruzioni
La dichiarazione delle rotte contiene attualmente solo l'ID del modello da utilizzare. Quando si visualizza una nuova pagina, a volte è necessario un po 'di più. L'implementazione del routing viene migliorata con due funzionalità aggiuntive:
- Assegnare titoli a ciascun modello e aggiornare il titolo della finestra con questo nuovo titolo quando il modello cambia.
- Aggiungere un'opzione per eseguire del codice dopo le modifiche al modello. Si vuole stampare `"Il cruscotto è mostrato" nella` console per sviluppatori ogni volta che viene visualizzata la pagina del dashboard.
## Rubrica
| Criteri | Ottimo | Adeguato | Necessita miglioramento |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| | Le due funzionalità sono implementate e funzionanti. L'aggiunta di titolo e codice funziona anche per una nuova rotta aggiunta nella dichiarazione di `routes` . | Sono funzionanti i due comportamenti aggiuntivi, ma il comportamento è fisso nel codice e non è configurabile tramite la dichiarazione di `routes`. L'aggiunta di una terza rotta con l'aggiunta di titolo e codice non funziona o funziona parzialmente. | Una delle funzionalità manca o non funziona correttamente. |

View File

@@ -1,14 +0,0 @@
# ルーティングの改善
## 説明書
The routes declaration contains currently only the template ID to use. But when displaying a new page, a bit more is needed sometimes. Let's improve our routing implementation with two additional features:
- Give titles to each template and update the window title with this new title when the template changes.
- Add an option to run some code after the template changes. We want to print `'Dashboard is shown'` in the developer console every time the dashboard page is displayed.
## ルーブリック
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| | The two features are implemented and working. Title and code addition also work for a new route added in the `routes` declaration. | The two features work, but the behavior is hardcoded and not configurable via the `routes` declaration. Adding a third route with title and code addition does not work or works partially. | One of the features is missing or not working properly. |

View File

@@ -1,14 +0,0 @@
# 라우팅 개선
## 설명
경로 선언에는 현재 사용할 템플릿 ID만 포함됩니다. 하지만 새 페이지를 표시할 때는 추가할 것이 더 생기는 경우가 있습니다. 두 가지 추가 기능을 사용하여 라우팅 구현을 개선해 봅시다.
- 각 템플릿에 제목을 부여하고 템플릿이 변경되면 새 제목으로 창 제목을 변경합니다.
- 템플릿 변경 후 일부 코드를 실행하는 옵션을 추가합니다. 대시보드 페이지가 표시될 때마다 개발자 콘솔에 `'대시보드가 보임'`을 출력합니다.
## 평가 기준
기준 | 모범 답안 | 적당한 답안 | 개선이 필요한 답안
--- | --- | --- | ---
| 두 기능이 구현되고 작동하는 경우. 제목 및 코드 추가는 `routes` 선언에 추가된 새 경로에서도 작동합니다. | 두 기능은 작동하지만, 동작은 하드 코딩되어 있으며 `routes` 선언을 통해 구성할 수 없는 경우. <br> 세 번째 경로를 제목과 코드와 함께 추가하면 작동하지 않거나 부분적으로 작동합니다. | 기능 중 하나가 없거나 제대로 작동하지 않는 경우

View File

@@ -1,14 +0,0 @@
# Tingkatkan penghalaan
## Arahan
Deklarasi laluan hanya mengandungi ID templat yang akan digunakan. Tetapi ketika memaparkan halaman baru, kadang-kadang diperlukan lebih banyak lagi. Mari tingkatkan pelaksanaan penghalaan kami dengan dua ciri tambahan:
- Berikan tajuk untuk setiap templat dan kemas kini tajuk tetingkap dengan tajuk baru ini apabila templat berubah.
- Tambahkan pilihan untuk menjalankan beberapa kod setelah templat berubah. Kami ingin mencetak `"Papan Pemuka ditunjukkan"` di konsol pembangun setiap kali halaman papan pemuka dipaparkan.
## Rubrik
| Kriteria | Contoh | Mencukupi | Usaha Lagi |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| | Kedua-dua ciri tersebut dilaksanakan dan berfungsi. Penambahan tajuk dan kod juga berfungsi untuk laluan baru yang ditambahkan dalam deklarasi `route` | Kedua-dua ciri berfungsi, tetapi tingkah laku itu dikodkan keras dan tidak dapat dikonfigurasi melalui deklarasi `route`. Menambah laluan ketiga dengan penambahan tajuk dan kod tidak berfungsi atau berfungsi secara separa. | Salah satu ciri hilang atau tidak berfungsi dengan baik. |

View File

@@ -1,14 +0,0 @@
# Verbeter de routing
## Instructies
De routes-declaratie bevat momenteel alleen de te gebruiken sjabloon-ID. Maar bij het tonen van een nieuwe pagina is soms iets meer nodig. Laten we onze routeringsimplementatie verbeteren met twee extra functies:
- Geef elk sjabloon een titel en werk de venstertitel bij met deze nieuwe titel wanneer de sjabloon verandert.
- Voeg een optie toe om wat code uit te voeren nadat de sjabloon is gewijzigd. Elke keer dat de dashboardpagina wordt weergegeven willen we `'Dashboard wordt weergegeven'` in de ontwikkelaarsconsole afdrukken.
## Rubriek
| Criteria | Voorbeeldig | Voldoende | Moet worden verbeterd |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| | De twee functies zijn geïmplementeerd en werken. Titel en codetoevoeging werken ook voor een nieuwe route die is toegevoegd in de `routes`-aangifte. | De twee functies werken, maar het gedrag is hard gecodeerd en kan niet worden geconfigureerd via de `routes`-aangifte. Het toevoegen van een derde route met toevoeging van titel en code werkt niet of gedeeltelijk. | Een van de functies ontbreekt of werkt niet goed. |

View File

@@ -1,14 +0,0 @@
# 增進網頁路由
## 簡介
我們的網頁路由的定義只包含模板的 ID。但當顯示新的網頁頁面時我們或許會用到更多東西。讓我們來增進我們的網頁路由方式新增兩項功能
- 給各個模板標題,在模板切換後同時更新網頁視窗的標題。
- 加入額外選項,在模板切換後執行特定程式。我們希望在切換到儀表板頁面時,在開發者命令欄顯示 `'Dashboard is shown'`
## 學習評量
| 作業內容 | 優良 | 普通 | 待改進 |
| -------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------ |
| | 兩個新功能運作正常,標題與程式也能執行新的 `routes` 規則 | 兩個新功能運作正常,但行為是 hardcoded 上去而非使用 `routes` 規則。新的路由規則無法完整地運作 | 新功能不完全或不正常運行 |