mirror of
https://github.com/microsoft/Web-Dev-For-Beginners.git
synced 2025-08-31 18:32:16 +02:00
Merge branch 'main' into nl
This commit is contained in:
@@ -41,7 +41,7 @@ If you want to create multiples screens for a web page, one solution would be to
|
||||
- You have to reload the entire HTML when switching screen, which can be slow.
|
||||
- It's difficult to share data between the different screens.
|
||||
|
||||
Another approach is have only one HTML file, and define multiple [HTML templates](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) using the `<template>` element. A template is a reusable HTML block that is not displayed by the browser, and needs to be instantiated at runtime using JavaScript.
|
||||
Another approach is have only one HTML file, and define multiple [HTML templates](https://developer.mozilla.org/docs/Web/HTML/Element/template) using the `<template>` element. A template is a reusable HTML block that is not displayed by the browser, and needs to be instantiated at runtime using JavaScript.
|
||||
|
||||
### Task
|
||||
|
||||
@@ -107,9 +107,9 @@ If you try your current HTML file in a browser, you'll see that it get stuck dis
|
||||
|
||||
Instantiating a template is usually done in 3 steps:
|
||||
|
||||
1. Retrieve the template element in the DOM, for example using [`document.getElementById`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById).
|
||||
2. Clone the template element, using [`cloneNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode).
|
||||
3. Attach it to the DOM under a visible element, for example using [`appendChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild).
|
||||
1. Retrieve the template element in the DOM, for example using [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
|
||||
2. Clone the template element, using [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
|
||||
3. Attach it to the DOM under a visible element, for example using [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild).
|
||||
|
||||
✅ Why do we need to clone the template before attaching it to the DOM? What do you think would happen if we skipped this step?
|
||||
|
||||
@@ -174,7 +174,7 @@ const routes = {
|
||||
};
|
||||
```
|
||||
|
||||
Now let's modify a bit the `updateRoute` function. Instead of passing directly the `templateId` as an argument, we want to retrieve it by first looking at the current URL, and then use our map to get the corresponding template ID value. We can use [`window.location.pathname`](https://developer.mozilla.org/en-US/docs/Web/API/Location/pathname) to get only the path section from the URL.
|
||||
Now let's modify a bit the `updateRoute` function. Instead of passing directly the `templateId` as an argument, we want to retrieve it by first looking at the current URL, and then use our map to get the corresponding template ID value. We can use [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname) to get only the path section from the URL.
|
||||
|
||||
```js
|
||||
function updateRoute() {
|
||||
@@ -202,9 +202,9 @@ The next step for our app is to add the possibility to navigate between pages wi
|
||||
|
||||
We already took care of the second part with the `updateRoute` function, so we have to figure out how to update the current URL.
|
||||
|
||||
We'll have to use JavaScript and more specifically the [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) that allows to update the URL and create a new entry in the browsing history, without reloading the HTML.
|
||||
We'll have to use JavaScript and more specifically the [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState) that allows to update the URL and create a new entry in the browsing history, without reloading the HTML.
|
||||
|
||||
> Note: While the HTML anchor element [`<a href>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) can be used on its own to create hyperlinks to different URLs, it will make the browser reload the HTML by default. It is necessary to prevent this behavior when handling routing with custom javascript, using the preventDefault() function on the click event.
|
||||
> Note: While the HTML anchor element [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) can be used on its own to create hyperlinks to different URLs, it will make the browser reload the HTML by default. It is necessary to prevent this behavior when handling routing with custom javascript, using the preventDefault() function on the click event.
|
||||
|
||||
### Task
|
||||
|
||||
@@ -252,7 +252,7 @@ Let's complete the navigation system by adding bindings to our *Login* and *Logo
|
||||
<a href="/login" onclick="onLinkClick()">Logout</a>
|
||||
```
|
||||
|
||||
Using the [`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) attribute bind the `click` event to JavaScript code, here the call to the `navigate()` function.
|
||||
Using the [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) attribute bind the `click` event to JavaScript code, here the call to the `navigate()` function.
|
||||
|
||||
Try clicking on these links, you should be now able to navigate between the different screens of your app.
|
||||
|
||||
@@ -266,7 +266,7 @@ Using the `history.pushState` creates new entries in the browser's navigation hi
|
||||
|
||||
If you try clicking on the back button a few times, you'll see that the current URL changes and the history is updated, but the same template keeps being displayed.
|
||||
|
||||
That's because don't know that we need to call `updateRoute()` every time the history changes. If you take a look at the [`history.pushState` documentation](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState), you can see that if the state changes - meaning that we moved to a different URL - the [`popstate`](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event) event is triggered. We'll use that to fix that issue.
|
||||
That's because don't know that we need to call `updateRoute()` every time the history changes. If you take a look at the [`history.pushState` documentation](https://developer.mozilla.org/docs/Web/API/History/pushState), you can see that if the state changes - meaning that we moved to a different URL - the [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) event is triggered. We'll use that to fix that issue.
|
||||
|
||||
### Task
|
||||
|
||||
@@ -277,7 +277,7 @@ window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> Note: we used an [arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) here to declare our `popstate` event handler for conciseness, but a regular function would work the same.
|
||||
> Note: we used an [arrow function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) here to declare our `popstate` event handler for conciseness, but a regular function would work the same.
|
||||
|
||||
Here's a refresher video on arrow functions:
|
||||
|
||||
@@ -299,7 +299,7 @@ Add a new template and route for a third page that shows the credits for this ap
|
||||
|
||||
## Review & Self Study
|
||||
|
||||
Routing is one of the surprisingly tricky parts of web development, especially as the web moves from page refresh behaviors to Single Page Application page refreshes. Read a little about [how the Azure Static Web App service](https://docs.microsoft.com/en-us/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa) handles routing. Can you explain why some of the decisions described on that document are necessary?
|
||||
Routing is one of the surprisingly tricky parts of web development, especially as the web moves from page refresh behaviors to Single Page Application page refreshes. Read a little about [how the Azure Static Web App service](https://docs.microsoft.com/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa) handles routing. Can you explain why some of the decisions described on that document are necessary?
|
||||
|
||||
## Assignment
|
||||
|
||||
|
@@ -40,7 +40,7 @@ Si desea crear varias pantallas para una página web, una solución sería crear
|
||||
- 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/en-US/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.
|
||||
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:
|
||||
|
||||
@@ -105,9 +105,9 @@ Si prueba su archivo HTML actual en un navegador, verá que se atasca mostrando
|
||||
|
||||
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/en-US/docs/Web/API/Document/getElementById).
|
||||
2. Clone el elemento de plantilla, usando [`cloneNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode).
|
||||
3. Adjúntelo al DOM bajo un elemento visible, por ejemplo usando [ʻappendChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild).
|
||||
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?
|
||||
|
||||
@@ -172,7 +172,7 @@ const routes = {
|
||||
};
|
||||
```
|
||||
|
||||
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/en-US/docs/Web/API/Location/pathname) para obtener solo la sección de ruta de la URL.
|
||||
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() {
|
||||
@@ -199,9 +199,9 @@ El siguiente paso para nuestra aplicación es agregar la posibilidad de navegar
|
||||
|
||||
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/en-US/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.
|
||||
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/en-US/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.
|
||||
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
|
||||
|
||||
@@ -241,7 +241,7 @@ Completemos el sistema de navegación agregando enlaces a nuestros botones *logi
|
||||
<button onclick="navigate('/login')">Logout</button>
|
||||
```
|
||||
|
||||
Usando el atributo [`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) enlaza el evento `click` al código JavaScript, aquí la llamada al` navigate()`función.
|
||||
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.
|
||||
|
||||
@@ -255,7 +255,7 @@ El uso de `history.pushState` crea nuevas entradas en el historial de navegació
|
||||
|
||||
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/en-US/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/en-US/docs/Web/API/Window/popstate_event). Lo usaremos para solucionar ese problema.
|
||||
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
|
||||
|
||||
@@ -267,7 +267,7 @@ window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> Nota: utilizamos una [función de flecha](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) aquí para declarar nuestro controlador de eventos `popstate` por concisión, pero un la función regular funcionaría igual.
|
||||
> 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 un la función regular funcionaría igual.
|
||||
|
||||
Ahora intente utilizar los botones de avance y retroceso de sus navegadores y compruebe que esta vez lo que se muestra está actualizado correctamente.
|
||||
|
||||
|
@@ -41,7 +41,7 @@ Se si desidera creare più schermate per una pagina Web, una soluzione potrebbe
|
||||
- È 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/en-US/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.
|
||||
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à
|
||||
|
||||
@@ -108,7 +108,7 @@ Se si prova il proprio file HTML corrente in un browser, si vedrà che si blocca
|
||||
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/en-US/docs/Web/API/Node/cloneNode).
|
||||
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?
|
||||
@@ -174,7 +174,7 @@ const routes = {
|
||||
};
|
||||
```
|
||||
|
||||
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/en-US/docs/Web/API/Location/pathname) per ottenere solo la sezione del percorso dall'URL.
|
||||
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() {
|
||||
@@ -202,7 +202,7 @@ Il prossimo passo per la costruzione dell'app è aggiungere la possibilità di n
|
||||
|
||||
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/en-US/docs/Web/API/History/pushState) che permette di aggiornare l'URL e creare una nuova voce nella cronologia di navigazione, senza ricaricare l'HTML.
|
||||
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.
|
||||
|
||||
@@ -252,7 +252,7 @@ Si completa il sistema di navigazione aggiungendo collegamenti ai link di access
|
||||
<a href="/login" onclick="onLinkClick()">Logout</a>
|
||||
```
|
||||
|
||||
Utilizzando l 'attributo [`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) associare l'evento `click` al codice JavaScript, in questo caso la chiamata alla funzione `navigate()` .
|
||||
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.
|
||||
|
||||
@@ -266,7 +266,7 @@ L'utilizzo di `history.pushState` crea nuove voci nella cronologia di navigazion
|
||||
|
||||
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/en-US/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/en-US/docs/Web/API/Window/popstate_event) `popstate`. Verrà usato per risolvere quel problema.
|
||||
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à
|
||||
|
||||
@@ -277,7 +277,7 @@ window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> Nota: è stata usata una [funzione freccia](https://developer.mozilla.org/en-US/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.
|
||||
> 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:
|
||||
|
||||
@@ -299,7 +299,7 @@ Aggiungere un nuovo modello e instradare per una terza pagina che mostra i credi
|
||||
|
||||
## 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/en-us/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?
|
||||
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
|
||||
|
||||
|
@@ -174,7 +174,7 @@ const routes = {
|
||||
};
|
||||
```
|
||||
|
||||
では、`updateRoute` 関数を少し修正してみましょう。引数に `templateId` を直接渡すのではなく、まず現在の URL を見て、map を使って対応するテンプレート ID の値を取得したいと思います。URL からパス部分だけを取得するには、[`window.location.pathname`](https://developer.mozilla.org/en-US/docs/Web/API/Location/pathname)を使うことができます。
|
||||
では、`updateRoute` 関数を少し修正してみましょう。引数に `templateId` を直接渡すのではなく、まず現在の URL を見て、map を使って対応するテンプレート ID の値を取得したいと思います。URL からパス部分だけを取得するには、[`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname)を使うことができます。
|
||||
|
||||
```js
|
||||
function updateRoute() {
|
||||
@@ -266,7 +266,7 @@ HTML の *Login* と *Logout* リンクにバインディングを追加して
|
||||
|
||||
何度か戻るボタンをクリックしてみると、現在の URL が変わって履歴が更新されていますが、同じテンプレートが表示され続けています。
|
||||
|
||||
これは、履歴が変わるたびに `updateRoute()` を呼び出す必要があることを知らないからです。[`history.pushState` のドキュメント](https://developer.mozilla.org/ja/docs/Web/API/History/pushState)を見てみると、状態が変化した場合、つまり別の URL に移動した場合には、[`popstate`](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event)イベントが発生することがわかります。これを使ってこの問題を解決しましょう。
|
||||
これは、履歴が変わるたびに `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)イベントが発生することがわかります。これを使ってこの問題を解決しましょう。
|
||||
|
||||
### タスク
|
||||
|
||||
|
@@ -41,7 +41,7 @@
|
||||
- 화면 전환 시 전체 HTML을 다시 불러와야 하므로, 속도가 느릴 수 있습니다.
|
||||
- 서로 다른 화면 간 데이터 공유가 어렵습니다.
|
||||
|
||||
또 다른 방법은 HTML 파일이 하나일 때, `<template>` 요소로 여러 [HTML templates](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)을 정의하는 것입니다. 템플릿은 브라우저에 보이지 않는 재사용 가능한 HTML 블록이면서, JavaScript를 사용해서 런타임에 인스턴스화합니다.
|
||||
또 다른 방법은 HTML 파일이 하나일 때, `<template>` 요소로 여러 [HTML templates](https://developer.mozilla.org/docs/Web/HTML/Element/template)을 정의하는 것입니다. 템플릿은 브라우저에 보이지 않는 재사용 가능한 HTML 블록이면서, JavaScript를 사용해서 런타임에 인스턴스화합니다.
|
||||
|
||||
### 작업
|
||||
|
||||
@@ -107,9 +107,9 @@
|
||||
|
||||
템플릿 인스턴스화는 일반적으로 3 단계로 진행됩니다:
|
||||
|
||||
1. [`document.getElementById`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)를 사용한 예시로, DOM에서 템플릿 요소 검색합니다.
|
||||
2. [`cloneNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode)로, 템플릿 요소를 복제합니다.
|
||||
3. [`appendChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)를 사용한 예시로, 보이는 요소 아래의 DOM에 붙입니다.
|
||||
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에 붙이기 전에 템플릿을 복제해야하는 이유는 무엇일까요? 이 단계를 넘기면 어떻게 될까요?
|
||||
|
||||
@@ -174,7 +174,7 @@ const routes = {
|
||||
};
|
||||
```
|
||||
|
||||
이제 `updateRoute` 함수를 약간 수정합니다. `templateId`를 인수로 직접 주는 대신, 먼저 현재 URL을 보고 찾은 다음, 맵을 사용하여 해당 템플릿 ID 값을 가져오려 합니다. [`window.location.pathname`](https://developer.mozilla.org/en-US/docs/Web/API/Location/pathname)으로 URL에서 경로 섹션만 가져올 수 있습니다.
|
||||
이제 `updateRoute` 함수를 약간 수정합니다. `templateId`를 인수로 직접 주는 대신, 먼저 현재 URL을 보고 찾은 다음, 맵을 사용하여 해당 템플릿 ID 값을 가져오려 합니다. [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname)으로 URL에서 경로 섹션만 가져올 수 있습니다.
|
||||
|
||||
```js
|
||||
function updateRoute() {
|
||||
@@ -202,9 +202,9 @@ function updateRoute() {
|
||||
|
||||
두 번째 부분은 `updateRoute` 함수로 이미 처리했으므로, 현재 URL로 갱신하는 방법을 알아냅니다.
|
||||
|
||||
HTML 앵커 요소 [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)를 사용하여 다른 URL에 대한 하이퍼링크를 만들 수 있지만, 여기에서 사용하면 브라우저가 HTML을 다시 불러오게 됩니다.
|
||||
HTML 앵커 요소 [`<a>`](https://developer.mozilla.org/docs/Web/HTML/Element/a)를 사용하여 다른 URL에 대한 하이퍼링크를 만들 수 있지만, 여기에서 사용하면 브라우저가 HTML을 다시 불러오게 됩니다.
|
||||
|
||||
대신 URL을 업데이트 할 수 있는 JavaScript와 더 구체적으로 [`history.pushState`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)를 사용해야합니다. HTML을 다시 불러오지 않고 검색 기록에 새로운 항목을 만듭니다.
|
||||
대신 URL을 업데이트 할 수 있는 JavaScript와 더 구체적으로 [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState)를 사용해야합니다. HTML을 다시 불러오지 않고 검색 기록에 새로운 항목을 만듭니다.
|
||||
|
||||
### 작업
|
||||
|
||||
@@ -243,7 +243,7 @@ HTML의 *Login*과 *Logout* 버튼에 바인딩을 추가하여 내비게이션
|
||||
<button onclick="navigate('/login')">Logout</button>
|
||||
```
|
||||
|
||||
[`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) 속성을 사용하여 `click` 이벤트를 JavaScript 코드로 바인딩합니다, 여기에서 `navigate()` 함수를 호출합니다.
|
||||
[`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) 속성을 사용하여 `click` 이벤트를 JavaScript 코드로 바인딩합니다, 여기에서 `navigate()` 함수를 호출합니다.
|
||||
|
||||
이 버튼들을 클릭해보세요, 이제 앱의 여러 화면들을 이동할 수 있습니다.
|
||||
|
||||
@@ -257,7 +257,7 @@ HTML의 *Login*과 *Logout* 버튼에 바인딩을 추가하여 내비게이션
|
||||
|
||||
뒤로가기 버튼을 몇 번 클릭하면, 현재 URL이 변경되며 히스토리가 갱신되지만 동일한 템플릿이 계속 출력되는 것을 볼 수 있습니다.
|
||||
|
||||
히스토리가 바뀔 때마다 `updateRoute()`를 호출해야 한다는 사실을 모르기 때문입니다. [`history.pushState` documentation](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState)을 살펴보면, 상태가 바뀌는 지 확인할 수 있습니다 - 다른 URL로 이동했다고 의미합니다. - [`popstate`](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event) 이벤트가 연결됩니다. 이 이슈를 해결하는 데 사용할 것입니다.
|
||||
히스토리가 바뀔 때마다 `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) 이벤트가 연결됩니다. 이 이슈를 해결하는 데 사용할 것입니다.
|
||||
|
||||
### 작업
|
||||
|
||||
@@ -268,7 +268,7 @@ window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> Note: 여기서는 간결함을 위해 [arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)을 사용하여 `popstate` 이벤트 핸들러를 선언했지만, 일반적인 함수와 동일하게 작동합니다.
|
||||
> Note: 여기서는 간결함을 위해 [arrow function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions)을 사용하여 `popstate` 이벤트 핸들러를 선언했지만, 일반적인 함수와 동일하게 작동합니다.
|
||||
|
||||
다음은 화살표 함수에 대한 복습 동영상입니다:
|
||||
|
||||
@@ -288,7 +288,7 @@ updateRoute();
|
||||
|
||||
## 리뷰 & 자기주도 학습
|
||||
|
||||
라우팅은 웹 개발의 놀랍고 까다로운 부분 중 하나입니다, 특히 웹의 페이지 새로고침 동작에서 단일 페이지 애플리케이션 페이지 새로고침으로 이동함에 따라 더욱 더 그렇습니다. [how the Azure Static Web App service](https://docs.microsoft.com/en-us/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa)의 라우터 제어에 대해 약간 봅니다. 그 문서에 기술된 몇 가지 결정이 필요한 이유를 설명할 수 있나요?
|
||||
라우팅은 웹 개발의 놀랍고 까다로운 부분 중 하나입니다, 특히 웹의 페이지 새로고침 동작에서 단일 페이지 애플리케이션 페이지 새로고침으로 이동함에 따라 더욱 더 그렇습니다. [how the Azure Static Web App service](https://docs.microsoft.com/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa)의 라우터 제어에 대해 약간 봅니다. 그 문서에 기술된 몇 가지 결정이 필요한 이유를 설명할 수 있나요?
|
||||
|
||||
## 과제
|
||||
|
||||
|
@@ -41,7 +41,7 @@ Jika anda ingin membuat beberapa layar untuk halaman web, satu penyelesaiannya a
|
||||
- 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/en-US/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.
|
||||
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
|
||||
|
||||
@@ -107,9 +107,9 @@ Sekiranya anda mencuba fail HTML semasa anda dalam penyemak imbas, anda akan mel
|
||||
|
||||
Membuat templat biasanya dilakukan dalam 3 langkah:
|
||||
|
||||
1. Dapatkan semula elemen templat di DOM, misalnya menggunakan [`document.getElementById`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById).
|
||||
2. Klon elemen templat, menggunakan [`cloneNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode).
|
||||
3. Lampirkan ke DOM di bawah elemen yang kelihatan, misalnya menggunakan [`appendChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild).
|
||||
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?
|
||||
|
||||
@@ -174,7 +174,7 @@ const routes = {
|
||||
};
|
||||
```
|
||||
|
||||
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/en-US/docs/Web/API/Location/pathname) untuk mendapatkan hanya bahagian jalan dari URL.
|
||||
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() {
|
||||
@@ -202,9 +202,9 @@ Langkah seterusnya untuk aplikasi kita adalah menambahkan kemungkinan untuk mena
|
||||
|
||||
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/en-US/docs/Web/API/History/pushState) yang memungkinkan untuk mengemas kini URL dan buat entri baru dalam sejarah penyemakan imbas, tanpa memuatkan semula HTML.
|
||||
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/en-US/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.
|
||||
> 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
|
||||
|
||||
@@ -252,7 +252,7 @@ Mari lengkapkan sistem navigasi dengan menambahkan pengikatan pada pautan *Login
|
||||
<a href="/login" onclick="onLinkClick()">Logout</a>
|
||||
```
|
||||
|
||||
Menggunakan atribut [`onclick`](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick) mengikat peristiwa`klik` ke kod JavaScript, di sini panggilan ke `navigasi() `fungsi.
|
||||
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.
|
||||
|
||||
@@ -266,7 +266,7 @@ Menggunakan `history.pushState` membuat entri baru dalam sejarah navigasi penyem
|
||||
|
||||
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/en-US/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/en-US/docs/Web/API/Window/popstate_event) dicetuskan. Kami akan menggunakannya untuk menyelesaikan masalah itu.
|
||||
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
|
||||
|
||||
@@ -277,7 +277,7 @@ window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> Catatan: kami menggunakan [fungsi panah](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) di sini untuk menyatakan pengendali acara `popstate` kami untuk kesimpulan, fungsi biasa akan berfungsi sama.
|
||||
> 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:
|
||||
|
||||
@@ -299,7 +299,7 @@ Tambahkan templat dan laluan baru untuk halaman ketiga yang menunjukkan kredit u
|
||||
|
||||
## 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/en-us/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa) menangani penghalaan . Bolehkah anda menjelaskan mengapa beberapa keputusan yang dijelaskan pada dokumen itu diperlukan?
|
||||
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-13441-cxa) menangani penghalaan . Bolehkah anda menjelaskan mengapa beberapa keputusan yang dijelaskan pada dokumen itu diperlukan?
|
||||
|
||||
## Tugasan
|
||||
|
||||
|
307
7-bank-project/1-template-route/translations/README.zh-tw.md
Normal file
307
7-bank-project/1-template-route/translations/README.zh-tw.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# 建立銀行網頁應用程式 Part 1:HTML 模板與網頁路由
|
||||
|
||||
## 課前測驗
|
||||
|
||||
[課前測驗](https://nice-beach-0fe9e9d0f.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/en-US/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/en-US/docs/Web/API/Document/getElementById)。
|
||||
2. 複製模板元素,使用 [`cloneNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode)。
|
||||
3. 將複製元素接到 DOM 的顯示元素上,例如使用 [`appendChild`](https://developer.mozilla.org/en-US/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/en-US/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/en-US/docs/Web/API/History/pushState),更新網址位置並建立瀏覽紀錄,同時不更新整個 HTML 頁面。
|
||||
|
||||
> 筆記:網頁超連結元素 [`<a href>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) 可以建立不同網址的連接,但它預設上會讓瀏覽器重新載入 HTML 檔。我們需要手動新增 JavaScript 處理路由以避免此行為發生,在點擊事件中使用函式 preventDefault() 。
|
||||
|
||||
### 課題
|
||||
|
||||
我們來建立新的函式,讓應用程式得以做網頁的訪問:
|
||||
|
||||
```js
|
||||
function navigate(path) {
|
||||
window.history.pushState({}, path, window.location.origin + 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()">Login</a>
|
||||
...
|
||||
<a href="/login" onclick="onLinkClick()">Logout</a>
|
||||
```
|
||||
|
||||
使用 [`onclick`](https://developer.mozilla.org/en-US/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` 會建立瀏覽器的瀏覽紀錄。你可以使用瀏覽器的*上一頁*來確認,它應該要能呈現像這樣的畫面:
|
||||
|
||||

|
||||
|
||||
點擊上一頁數次,你會看到網址會改變且歷史紀錄也更新上去了,但同一個模板還是被顯示出來。
|
||||
|
||||
這是因為網頁不知道該如何依據歷史紀錄來呼叫 `updateRoute()`。如果你閱讀了 [`history.pushState` 技術文件](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState),你會發現如果狀態改變 ── 同時代表著網址改變 ── [`popstate`](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event) 事件就會被觸發。我們會利用此特徵來修復這個問題。
|
||||
|
||||
### 課題
|
||||
|
||||
為了在瀏覽器歷史改變時更新該被顯示的模板,我們會以新函式來呼叫 `updateRoute()`。我們在 `app.js` 檔最下方加入:
|
||||
|
||||
```js
|
||||
window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
```
|
||||
|
||||
> 筆記:我們在這裡使用[箭頭函式](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions),簡短地宣告 `popstate` 事件處理器。它與正規的函式的功能是一樣的。
|
||||
|
||||
這是關於箭頭函式的回想影片:
|
||||
|
||||
[](https://youtube.com/watch?v=OP6eEbOj2sc "箭頭函式")
|
||||
|
||||
> 點擊上方圖片以觀看關於箭頭函式的影片。
|
||||
|
||||
現在,試著點擊瀏覽器上的上一頁與下一頁,檢查這次模板是否正確地更新出來。
|
||||
|
||||
---
|
||||
|
||||
## 🚀 挑戰
|
||||
|
||||
加入新的模板與對應的關聯表,顯示出本應用程式第三頁的功能 ── 帳戶餘額。
|
||||
|
||||
## 課後測驗
|
||||
|
||||
[課後測驗](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/42?loc=zh_tw)
|
||||
|
||||
## 複習與自學
|
||||
|
||||
網頁路由是網頁開發中很棘手的部分,特別是將網頁切換轉變為單一頁面應用程式(Single Page Application)。閱讀關於[Azure Static Web App 提供服務的方式](https://docs.microsoft.com/en-us/azure/static-web-apps/routes?WT.mc_id=academic-13441-cxa)以處理網頁路由。你能解釋為什麼文件上的某些決定會如此重要呢?
|
||||
|
||||
## 作業
|
||||
|
||||
[增進網頁路由](assignment.zh-tw.md)
|
@@ -0,0 +1,14 @@
|
||||
# 增進網頁路由
|
||||
|
||||
## 簡介
|
||||
|
||||
我們的網頁路由的定義只包含模板的 ID。但當顯示新的網頁頁面時,我們或許會用到更多東西。讓我們來增進我們的網頁路由方式,新增兩項功能:
|
||||
|
||||
- 給各個模板標題,在模板切換後同時更新網頁視窗的標題。
|
||||
- 加入額外選項,在模板切換後執行特定程式。我們希望在切換到儀表板頁面時,在開發者命令欄顯示 `'Dashboard is shown'`。
|
||||
|
||||
## 學習評量
|
||||
|
||||
| 作業內容 | 優良 | 普通 | 待改進 |
|
||||
| -------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------ |
|
||||
| | 兩個新功能運作正常,標題與程式也能執行新的 `routes` 規則 | 兩個新功能運作正常,但行為是 hardcoded 上去而非使用 `routes` 規則。新的路由規則無法完整地運作 | 新功能不完全或不正常運行 |
|
Reference in New Issue
Block a user