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

538 lines
52 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "2c1164912414820c8efd699b43f64954",
"translation_date": "2025-10-23T21:09:30+00:00",
"source_file": "7-bank-project/3-data/README.md",
"language_code": "th"
}
-->
# สร้างแอปธนาคาร ตอนที่ 3: วิธีการดึงและใช้งานข้อมูล
ลองนึกถึงคอมพิวเตอร์ของ Enterprise ใน Star Trek - เมื่อกัปตัน Picard ขอข้อมูลสถานะของยาน ข้อมูลจะปรากฏขึ้นทันทีโดยที่อินเทอร์เฟซไม่ต้องปิดและสร้างใหม่ทั้งหมด การไหลลื่นของข้อมูลแบบนี้คือสิ่งที่เรากำลังสร้างด้วยการดึงข้อมูลแบบไดนามิก
ตอนนี้แอปธนาคารของคุณเหมือนกับหนังสือพิมพ์ที่พิมพ์ออกมา - มีข้อมูลแต่ไม่เปลี่ยนแปลง เราจะเปลี่ยนมันให้เป็นเหมือนศูนย์ควบคุมภารกิจของ NASA ที่ข้อมูลไหลเวียนอย่างต่อเนื่องและอัปเดตแบบเรียลไทม์โดยไม่รบกวนการทำงานของผู้ใช้
คุณจะได้เรียนรู้วิธีการสื่อสารกับเซิร์ฟเวอร์แบบอะซิงโครนัส จัดการข้อมูลที่มาถึงในเวลาต่างกัน และเปลี่ยนข้อมูลดิบให้เป็นสิ่งที่มีความหมายสำหรับผู้ใช้ นี่คือความแตกต่างระหว่างการสาธิตและซอฟต์แวร์ที่พร้อมใช้งานจริง
## แบบทดสอบก่อนเรียน
[แบบทดสอบก่อนเรียน](https://ff-quizzes.netlify.app/web/quiz/45)
### สิ่งที่ต้องเตรียมก่อนเริ่ม
ก่อนที่จะเริ่มต้นการดึงข้อมูล ให้แน่ใจว่าคุณมีสิ่งเหล่านี้พร้อม:
- **บทเรียนก่อนหน้า**: ทำแบบฟอร์ม [เข้าสู่ระบบและลงทะเบียน](../2-forms/README.md) ให้เสร็จ - เราจะใช้เป็นพื้นฐานในการสร้าง
- **เซิร์ฟเวอร์ในเครื่อง**: ติดตั้ง [Node.js](https://nodejs.org) และ [เรียกใช้ API เซิร์ฟเวอร์](../api/README.md) เพื่อให้ข้อมูลบัญชี
- **การเชื่อมต่อ API**: ทดสอบการเชื่อมต่อเซิร์ฟเวอร์ของคุณด้วยคำสั่งนี้:
```bash
curl http://localhost:5000/api
# Expected response: "Bank API v1.0.0"
```
การทดสอบอย่างรวดเร็วนี้ช่วยให้มั่นใจว่าทุกองค์ประกอบสามารถสื่อสารกันได้อย่างถูกต้อง:
- ตรวจสอบว่า Node.js ทำงานได้อย่างถูกต้องในระบบของคุณ
- ยืนยันว่าเซิร์ฟเวอร์ API ของคุณทำงานและตอบสนอง
- ตรวจสอบว่าแอปของคุณสามารถเข้าถึงเซิร์ฟเวอร์ได้ (เหมือนการตรวจสอบการติดต่อวิทยุก่อนเริ่มภารกิจ)
---
## การทำความเข้าใจการดึงข้อมูลในแอปเว็บสมัยใหม่
วิธีที่แอปพลิเคชันเว็บจัดการข้อมูลได้พัฒนาขึ้นอย่างมากในช่วงสองทศวรรษที่ผ่านมา การทำความเข้าใจวิวัฒนาการนี้จะช่วยให้คุณเข้าใจว่าทำไมเทคนิคสมัยใหม่อย่าง AJAX และ Fetch API ถึงมีประสิทธิภาพและกลายเป็นเครื่องมือสำคัญสำหรับนักพัฒนาเว็บ
มาสำรวจดูว่าการทำงานของเว็บไซต์แบบดั้งเดิมแตกต่างจากแอปพลิเคชันที่ตอบสนองและไดนามิกในปัจจุบันอย่างไร
### แอปพลิเคชันแบบหลายหน้า (MPA)
ในยุคแรกของเว็บ ทุกครั้งที่คลิกเหมือนกับการเปลี่ยนช่องบนโทรทัศน์เก่า - หน้าจอจะว่างเปล่า แล้วค่อยๆ ปรับเข้าสู่เนื้อหาใหม่ นี่คือความจริงของแอปพลิเคชันเว็บในยุคแรก ที่ทุกการโต้ตอบหมายถึงการสร้างหน้าใหม่ทั้งหมดจากศูนย์
```mermaid
sequenceDiagram
participant User
participant Browser
participant Server
User->>Browser: Clicks link or submits form
Browser->>Server: Requests new HTML page
Note over Browser: Page goes blank
Server->>Browser: Returns complete HTML page
Browser->>User: Displays new page (flash/reload)
```
![กระบวนการอัปเดตในแอปพลิเคชันแบบหลายหน้า](../../../../translated_images/mpa.7f7375a1a2d4aa779d3f928a2aaaf9ad76bcdeb05cfce2dc27ab126024050f51.th.png)
**ทำไมวิธีนี้ถึงดูไม่ราบรื่น:**
- ทุกครั้งที่คลิกหมายถึงการสร้างหน้าใหม่ทั้งหมด
- ผู้ใช้ถูกขัดจังหวะกลางความคิดด้วยการกระพริบหน้าจอที่น่ารำคาญ
- การเชื่อมต่ออินเทอร์เน็ตทำงานหนักเพื่อดาวน์โหลดส่วนหัวและส่วนท้ายซ้ำๆ
- แอปพลิเคชันรู้สึกเหมือนการค้นหาเอกสารในตู้เก็บเอกสารมากกว่าการใช้ซอฟต์แวร์
### แอปพลิเคชันแบบหน้าเดียว (SPA)
AJAX (Asynchronous JavaScript and XML) เปลี่ยนแปลงรูปแบบนี้ไปอย่างสิ้นเชิง เหมือนกับการออกแบบแบบโมดูลของสถานีอวกาศนานาชาติ ที่นักบินอวกาศสามารถเปลี่ยนส่วนประกอบแต่ละส่วนได้โดยไม่ต้องสร้างโครงสร้างทั้งหมดใหม่ AJAX ช่วยให้เราสามารถอัปเดตส่วนเฉพาะของหน้าเว็บได้โดยไม่ต้องโหลดใหม่ทั้งหมด แม้ว่าชื่อจะกล่าวถึง XML แต่ปัจจุบันเราใช้ JSON เป็นหลัก แต่หลักการสำคัญยังคงเหมือนเดิม: อัปเดตเฉพาะสิ่งที่ต้องเปลี่ยนแปลง
```mermaid
sequenceDiagram
participant User
participant Browser
participant JavaScript
participant Server
User->>Browser: Interacts with page
Browser->>JavaScript: Triggers event handler
JavaScript->>Server: Fetches only needed data
Server->>JavaScript: Returns JSON data
JavaScript->>Browser: Updates specific page elements
Browser->>User: Shows updated content (no reload)
```
![กระบวนการอัปเดตในแอปพลิเคชันแบบหน้าเดียว](../../../../translated_images/spa.268ec73b41f992c2a21ef9294235c6ae597b3c37e2c03f0494c2d8857325cc57.th.png)
**ทำไม SPA ถึงดีกว่า:**
- อัปเดตเฉพาะส่วนที่เปลี่ยนแปลงจริงๆ (ฉลาดใช่ไหม?)
- ไม่มีการขัดจังหวะที่น่ารำคาญ - ผู้ใช้สามารถทำงานต่อได้อย่างต่อเนื่อง
- ข้อมูลที่เดินทางผ่านเครือข่ายน้อยลง หมายถึงการโหลดที่เร็วขึ้น
- ทุกอย่างรู้สึกเร็วและตอบสนองได้ดี เหมือนแอปบนมือถือของคุณ
### การพัฒนาไปสู่ Fetch API สมัยใหม่
เบราว์เซอร์สมัยใหม่มี [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API) ซึ่งแทนที่ [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest) แบบเก่า เหมือนกับความแตกต่างระหว่างการใช้โทรเลขและการใช้อีเมล Fetch API ใช้ promises เพื่อเขียนโค้ดอะซิงโครนัสที่สะอาดขึ้นและจัดการ JSON ได้อย่างเป็นธรรมชาติ
| คุณสมบัติ | XMLHttpRequest | Fetch API |
|-----------|----------------|-----------|
| **ไวยากรณ์** | ใช้ callback ที่ซับซ้อน | ใช้ promises ที่สะอาด |
| **การจัดการ JSON** | ต้องแปลงด้วยตนเอง | มี `.json()` ในตัว |
| **การจัดการข้อผิดพลาด** | ข้อมูลข้อผิดพลาดจำกัด | รายละเอียดข้อผิดพลาดครบถ้วน |
| **การสนับสนุนสมัยใหม่** | รองรับแบบเก่า | ใช้ promises และ async/await ของ ES6+ |
> 💡 **ความเข้ากันได้ของเบราว์เซอร์**: ข่าวดี - Fetch API ใช้งานได้ในเบราว์เซอร์สมัยใหม่ทั้งหมด! หากคุณอยากรู้เกี่ยวกับเวอร์ชันเฉพาะ [caniuse.com](https://caniuse.com/fetch) มีข้อมูลความเข้ากันได้ครบถ้วน
>
**สรุป:**
- ใช้งานได้ดีใน Chrome, Firefox, Safari และ Edge (พื้นฐานที่ผู้ใช้ของคุณอยู่)
- Internet Explorer เท่านั้นที่ต้องการความช่วยเหลือเพิ่มเติม (และจริงๆ ถึงเวลาปล่อย IE ไปแล้ว)
- เตรียมพร้อมสำหรับรูปแบบ async/await ที่สง่างามที่เราจะใช้ในภายหลัง
### การสร้างระบบเข้าสู่ระบบและการดึงข้อมูลบัญชี
ตอนนี้เรามาสร้างระบบเข้าสู่ระบบที่เปลี่ยนแอปธนาคารของคุณจากการแสดงผลแบบคงที่ไปเป็นแอปพลิเคชันที่ใช้งานได้จริง เหมือนกับโปรโตคอลการตรวจสอบสิทธิ์ที่ใช้ในสถานที่ปลอดภัยของทหาร เราจะตรวจสอบข้อมูลรับรองของผู้ใช้และให้สิทธิ์เข้าถึงข้อมูลเฉพาะของพวกเขา
เราจะสร้างสิ่งนี้ทีละขั้นตอน โดยเริ่มจากการตรวจสอบสิทธิ์พื้นฐานและเพิ่มความสามารถในการดึงข้อมูล
#### ขั้นตอนที่ 1: สร้างฟังก์ชันพื้นฐานสำหรับการเข้าสู่ระบบ
เปิดไฟล์ `app.js` ของคุณและเพิ่มฟังก์ชัน `login` ใหม่ ฟังก์ชันนี้จะจัดการกระบวนการตรวจสอบสิทธิ์ของผู้ใช้:
```javascript
async function login() {
const loginForm = document.getElementById('loginForm');
const user = loginForm.user.value;
}
```
**มาดูรายละเอียดกัน:**
- คำว่า `async`? มันบอก JavaScript ว่า "เฮ้ ฟังก์ชันนี้อาจต้องรออะไรบางอย่าง"
- เรากำลังดึงฟอร์มจากหน้า (แค่หาโดยใช้ ID)
- จากนั้นเราก็ดึงข้อมูลที่ผู้ใช้พิมพ์เป็นชื่อผู้ใช้
- นี่คือเคล็ดลับที่ดี: คุณสามารถเข้าถึงอินพุตของฟอร์มใดๆ โดยใช้แอตทริบิวต์ `name` - ไม่ต้องใช้ getElementById เพิ่มเติม!
> 💡 **รูปแบบการเข้าถึงฟอร์ม**: ทุกการควบคุมฟอร์มสามารถเข้าถึงได้โดยใช้ชื่อ (ตั้งค่าใน HTML ด้วยแอตทริบิวต์ `name`) เป็น property ของ element ฟอร์ม ซึ่งให้วิธีการที่สะอาดและอ่านง่ายในการดึงข้อมูลฟอร์ม
#### ขั้นตอนที่ 2: สร้างฟังก์ชันดึงข้อมูลบัญชี
ต่อไป เราจะสร้างฟังก์ชันเฉพาะเพื่อดึงข้อมูลบัญชีจากเซิร์ฟเวอร์ ซึ่งจะใช้รูปแบบเดียวกับฟังก์ชันการลงทะเบียนของคุณ แต่เน้นที่การดึงข้อมูล:
```javascript
async function getAccount(user) {
try {
const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user));
return await response.json();
} catch (error) {
return { error: error.message || 'Unknown error' };
}
}
```
**สิ่งที่โค้ดนี้ทำได้:**
- **ใช้** Fetch API สมัยใหม่เพื่อร้องขอข้อมูลแบบอะซิงโครนัส
- **สร้าง** URL คำขอ GET พร้อมพารามิเตอร์ชื่อผู้ใช้
- **ใช้** `encodeURIComponent()` เพื่อจัดการอักขระพิเศษใน URL อย่างปลอดภัย
- **แปลง** การตอบกลับเป็นรูปแบบ JSON เพื่อการจัดการข้อมูลที่ง่าย
- **จัดการ** ข้อผิดพลาดอย่างมีประสิทธิภาพโดยการส่งคืนวัตถุข้อผิดพลาดแทนการหยุดทำงาน
> ⚠️ **หมายเหตุด้านความปลอดภัย**: ฟังก์ชัน `encodeURIComponent()` จัดการอักข
สำหรับเนื้อหาที่ซับซ้อนมากขึ้น ให้ใช้ [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) ร่วมกับเมธอด [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append):
```javascript
// Safe way to create new elements
const transactionItem = document.createElement('div');
transactionItem.className = 'transaction-item';
transactionItem.textContent = `${transaction.date}: ${transaction.description}`;
container.append(transactionItem);
```
**ทำความเข้าใจวิธีนี้:**
- **สร้าง**องค์ประกอบ DOM ใหม่ด้วยโปรแกรม
- **ควบคุม**คุณสมบัติและเนื้อหาขององค์ประกอบได้อย่างเต็มที่
- **รองรับ**โครงสร้างองค์ประกอบที่ซับซ้อนและซ้อนกัน
- **รักษา**ความปลอดภัยโดยแยกโครงสร้างออกจากเนื้อหา
> ⚠️ **ข้อควรระวังด้านความปลอดภัย**: แม้ว่า [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) จะปรากฏในบทเรียนหลายๆ แห่ง แต่สามารถรันสคริปต์ที่ฝังอยู่ได้ เช่นเดียวกับมาตรการรักษาความปลอดภัยที่ CERN ที่ป้องกันการรันโค้ดที่ไม่ได้รับอนุญาต การใช้ `textContent` และ `createElement` เป็นทางเลือกที่ปลอดภัยกว่า
>
**ความเสี่ยงของ innerHTML:**
- รันแท็ก `<script>` ที่อยู่ในข้อมูลของผู้ใช้
- เสี่ยงต่อการโจมตีด้วยการฉีดโค้ด
- สร้างช่องโหว่ด้านความปลอดภัย
- ทางเลือกที่ปลอดภัยที่เราใช้นั้นให้ฟังก์ชันการทำงานที่เทียบเท่ากัน
### ทำให้ข้อผิดพลาดเป็นมิตรกับผู้ใช้
ปัจจุบัน ข้อผิดพลาดในการเข้าสู่ระบบปรากฏเฉพาะในคอนโซลของเบราว์เซอร์ ซึ่งผู้ใช้มองไม่เห็น เช่นเดียวกับความแตกต่างระหว่างการวินิจฉัยภายในของนักบินและระบบข้อมูลสำหรับผู้โดยสาร เราจำเป็นต้องสื่อสารข้อมูลสำคัญผ่านช่องทางที่เหมาะสม
การแสดงข้อความข้อผิดพลาดที่มองเห็นได้จะช่วยให้ผู้ใช้ได้รับข้อมูลทันทีเกี่ยวกับสิ่งที่ผิดพลาดและวิธีดำเนินการต่อไป
#### ขั้นตอนที่ 1: เพิ่มพื้นที่สำหรับข้อความข้อผิดพลาด
ก่อนอื่น ให้เพิ่มพื้นที่สำหรับข้อความข้อผิดพลาดใน HTML ของคุณ เพิ่มส่วนนี้ไว้ก่อนปุ่มเข้าสู่ระบบเพื่อให้ผู้ใช้มองเห็นได้ง่าย:
```html
<!-- This is where error messages will appear -->
<div id="loginError" role="alert"></div>
<button>Login</button>
```
**สิ่งที่เกิดขึ้นที่นี่:**
- เรากำลังสร้างคอนเทนเนอร์ว่างที่ยังคงมองไม่เห็นจนกว่าจะมีการใช้งาน
- วางตำแหน่งไว้ในที่ที่ผู้ใช้มักจะมองหลังจากคลิก "เข้าสู่ระบบ"
- `role="alert"` เป็นการเพิ่มที่ดีสำหรับโปรแกรมอ่านหน้าจอ - มันบอกเทคโนโลยีช่วยเหลือว่า "นี่คือสิ่งสำคัญ!"
- `id` ที่ไม่ซ้ำกันช่วยให้ JavaScript ของเราสามารถกำหนดเป้าหมายได้ง่าย
#### ขั้นตอนที่ 2: สร้างฟังก์ชันช่วยเหลือที่ใช้งานง่าย
มาสร้างฟังก์ชันยูทิลิตี้เล็กๆ ที่สามารถอัปเดตข้อความขององค์ประกอบใดๆ ได้ นี่เป็นหนึ่งในฟังก์ชัน "เขียนครั้งเดียว ใช้ได้ทุกที่" ที่จะช่วยประหยัดเวลา:
```javascript
function updateElement(id, text) {
const element = document.getElementById(id);
element.textContent = text;
}
```
**ประโยชน์ของฟังก์ชัน:**
- อินเทอร์เฟซที่เรียบง่ายที่ต้องการเพียง ID ขององค์ประกอบและเนื้อหาข้อความ
- ค้นหาและอัปเดตองค์ประกอบ DOM ได้อย่างปลอดภัย
- รูปแบบที่นำกลับมาใช้ใหม่ได้ซึ่งลดการทำซ้ำโค้ด
- รักษาพฤติกรรมการอัปเดตที่สอดคล้องกันทั่วทั้งแอปพลิเคชัน
#### ขั้นตอนที่ 3: แสดงข้อผิดพลาดในที่ที่ผู้ใช้สามารถมองเห็นได้
ตอนนี้มาแทนที่ข้อความคอนโซลที่ซ่อนอยู่ด้วยสิ่งที่ผู้ใช้สามารถมองเห็นได้จริง อัปเดตฟังก์ชันเข้าสู่ระบบของคุณ:
```javascript
// Instead of just logging to console, show the user what's wrong
if (data.error) {
return updateElement('loginError', data.error);
}
```
**การเปลี่ยนแปลงเล็กน้อยนี้สร้างความแตกต่างอย่างมาก:**
- ข้อความข้อผิดพลาดปรากฏในที่ที่ผู้ใช้กำลังมองหา
- ไม่มีการล้มเหลวแบบเงียบๆ อีกต่อไป
- ผู้ใช้ได้รับข้อมูลย้อนกลับที่สามารถดำเนินการได้ทันที
- แอปของคุณเริ่มให้ความรู้สึกเป็นมืออาชีพและใส่ใจ
ตอนนี้เมื่อคุณทดสอบด้วยบัญชีที่ไม่ถูกต้อง คุณจะเห็นข้อความข้อผิดพลาดที่เป็นประโยชน์ปรากฏบนหน้า!
![ภาพหน้าจอแสดงข้อความข้อผิดพลาดที่ปรากฏระหว่างการเข้าสู่ระบบ](../../../../translated_images/login-error.416fe019b36a63276764c2349df5d99e04ebda54fefe60c715ee87a28d5d4ad0.th.png)
#### ขั้นตอนที่ 4: การสร้างความครอบคลุมด้วยการเข้าถึง
นี่คือสิ่งที่น่าสนใจเกี่ยวกับ `role="alert"` ที่เราเพิ่มไว้ก่อนหน้านี้ - มันไม่ใช่แค่การตกแต่ง! คุณสมบัตินี้สร้างสิ่งที่เรียกว่า [Live Region](https://developer.mozilla.org/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) ที่ประกาศการเปลี่ยนแปลงให้โปรแกรมอ่านหน้าจอทราบทันที:
```html
<div id="loginError" role="alert"></div>
```
**เหตุผลที่สำคัญ:**
- ผู้ใช้โปรแกรมอ่านหน้าจอจะได้ยินข้อความข้อผิดพลาดทันทีที่มันปรากฏ
- ทุกคนได้รับข้อมูลสำคัญเดียวกัน ไม่ว่าจะนำทางอย่างไร
- เป็นวิธีง่ายๆ ในการทำให้แอปของคุณใช้งานได้สำหรับคนจำนวนมากขึ้น
- แสดงให้เห็นว่าคุณใส่ใจในการสร้างประสบการณ์ที่ครอบคลุม
การใส่ใจในรายละเอียดเล็กๆ น้อยๆ เช่นนี้แยกนักพัฒนาที่ดีออกจากนักพัฒนาที่ยอดเยี่ยม!
#### ขั้นตอนที่ 5: ใช้รูปแบบเดียวกันกับการลงทะเบียน
เพื่อความสอดคล้องกัน ให้ใช้การจัดการข้อผิดพลาดแบบเดียวกันในแบบฟอร์มการลงทะเบียนของคุณ:
1. **เพิ่ม**องค์ประกอบแสดงข้อผิดพลาดใน HTML การลงทะเบียนของคุณ:
```html
<div id="registerError" role="alert"></div>
```
2. **อัปเดต**ฟังก์ชันการลงทะเบียนของคุณเพื่อใช้รูปแบบการแสดงข้อผิดพลาดเดียวกัน:
```javascript
if (data.error) {
return updateElement('registerError', data.error);
}
```
**ประโยชน์ของการจัดการข้อผิดพลาดที่สอดคล้องกัน:**
- **ให้**ประสบการณ์ผู้ใช้ที่สม่ำเสมอในทุกแบบฟอร์ม
- **ลด**ภาระทางความคิดด้วยการใช้รูปแบบที่คุ้นเคย
- **ทำให้**การบำรุงรักษาง่ายขึ้นด้วยโค้ดที่นำกลับมาใช้ใหม่ได้
- **รับรอง**มาตรฐานการเข้าถึงทั่วทั้งแอป
## การสร้างแดชบอร์ดแบบไดนามิกของคุณ
ตอนนี้เราจะเปลี่ยนแดชบอร์ดแบบคงที่ของคุณให้เป็นอินเทอร์เฟซแบบไดนามิกที่แสดงข้อมูลบัญชีจริง เช่นเดียวกับความแตกต่างระหว่างตารางเวลาการบินที่พิมพ์กับบอร์ดแสดงการออกเดินทางแบบเรียลไทม์ที่สนามบิน เรากำลังเปลี่ยนจากข้อมูลแบบคงที่ไปเป็นการแสดงผลที่ตอบสนองแบบเรียลไทม์
ใช้เทคนิคการจัดการ DOM ที่คุณได้เรียนรู้ เราจะสร้างแดชบอร์ดที่อัปเดตโดยอัตโนมัติด้วยข้อมูลบัญชีปัจจุบัน
### ทำความรู้จักกับข้อมูลของคุณ
ก่อนที่เราจะเริ่มสร้าง มาดูข้อมูลประเภทที่เซิร์ฟเวอร์ของคุณส่งกลับมา เมื่อมีคนเข้าสู่ระบบสำเร็จ นี่คือข้อมูลที่คุณจะได้ใช้งาน:
```json
{
"user": "test",
"currency": "$",
"description": "Test account",
"balance": 75,
"transactions": [
{ "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
{ "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
{ "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
]
}
```
**โครงสร้างข้อมูลนี้ให้:**
- **`user`**: เหมาะสำหรับการปรับแต่งประสบการณ์ ("ยินดีต้อนรับกลับมา, Sarah!")
- **`currency`**: ทำให้แน่ใจว่าเราแสดงจำนวนเงินได้อย่างถูกต้อง
- **`description`**: ชื่อที่เป็นมิตรสำหรับบัญชี
- **`balance`**: ยอดคงเหลือปัจจุบันที่สำคัญที่สุด
- **`transactions`**: ประวัติการทำธุรกรรมทั้งหมดพร้อมรายละเอียด
ทุกสิ่งที่คุณต้องการเพื่อสร้างแดชบอร์ดธนาคารที่ดูเป็นมืออาชีพ!
> 💡 **เคล็ดลับมือโปร**: อยากเห็นแดชบอร์ดของคุณทำงานทันทีใช่ไหม? ใช้ชื่อผู้ใช้ `test` เมื่อเข้าสู่ระบบ - มันมาพร้อมกับข้อมูลตัวอย่างที่โหลดไว้ล่วงหน้าเพื่อให้คุณเห็นทุกอย่างทำงานโดยไม่ต้องสร้างธุรกรรมก่อน
>
**เหตุผลที่บัญชีทดสอบมีประโยชน์:**
- มาพร้อมกับข้อมูลตัวอย่างที่สมจริงที่โหลดไว้แล้ว
- เหมาะสำหรับการดูว่าการแสดงผลธุรกรรมทำงานอย่างไร
- ดีสำหรับการทดสอบฟีเจอร์ของแดชบอร์ด
- ช่วยให้คุณไม่ต้องสร้างข้อมูลจำลองด้วยตัวเอง
### การสร้างองค์ประกอบแสดงผลแดชบอร์ด
มาสร้างอินเทอร์เฟซแดชบอร์ดของคุณทีละขั้นตอน โดยเริ่มจากข้อมูลสรุปบัญชีและต่อด้วยฟีเจอร์ที่ซับซ้อนมากขึ้น เช่น รายการธุรกรรม
#### ขั้นตอนที่ 1: อัปเดตโครงสร้าง HTML ของคุณ
ก่อนอื่น แทนที่ส่วน "Balance" แบบคงที่ด้วยองค์ประกอบตัวแทนแบบไดนามิกที่ JavaScript ของคุณสามารถเติมข้อมูลได้:
```html
<section>
Balance: <span id="balance"></span><span id="currency"></span>
</section>
```
จากนั้นเพิ่มส่วนสำหรับคำอธิบายบัญชี เนื่องจากส่วนนี้ทำหน้าที่เป็นหัวข้อสำหรับเนื้อหาแดชบอร์ด ใช้ HTML เชิงความหมาย:
```html
<h2 id="description"></h2>
```
**ทำความเข้าใจโครงสร้าง HTML:**
- **ใช้**องค์ประกอบ `<span>` แยกสำหรับยอดคงเหลือและสกุลเงินเพื่อการควบคุมแยกกัน
- **กำหนด** ID ที่ไม่ซ้ำกันให้แต่ละองค์ประกอบเพื่อการกำหนดเป้าหมายด้วย JavaScript
- **ปฏิบัติตาม** HTML เชิงความหมายโดยใช้ `<h2>` สำหรับคำอธิบายบัญชี
- **สร้าง**ลำดับชั้นที่มีเหตุผลสำหรับโปรแกรมอ่านหน้าจอและ SEO
> ✅ **ข้อมูลเชิงลึกด้านการเข้าถึง**: คำอธิบายบัญชีทำหน้าที่เป็นหัวข้อสำหรับเนื้อหาแดชบอร์ด ดังนั้นจึงถูกทำเครื่องหมายเชิงความหมายเป็นหัวข้อ เรียนรู้เพิ่มเติมเกี่ยวกับวิธีที่ [โครงสร้างหัวข้อ](https://www.nomensa.com/blog/2017/how-structure-headings-web-accessibility) ส่งผลต่อการเข้าถึง คุณสามารถระบุองค์ประกอบอื่นๆ บนหน้าของคุณที่อาจได้รับประโยชน์จากแท็กหัวข้อได้หรือไม่?
#### ขั้นตอนที่ 2: สร้างฟังก์ชันอัปเดตแดชบอร์ด
ตอนนี้สร้างฟังก์ชันที่เติมข้อมูลแดชบอร์ดของคุณด้วยข้อมูลบัญชีจริง:
```javascript
function updateDashboard() {
if (!account) {
return navigate('/login');
}
updateElement('description', account.description);
updateElement('balance', account.balance.toFixed(2));
updateElement('currency', account.currency);
}
```
**ทีละขั้นตอน นี่คือสิ่งที่ฟังก์ชันนี้ทำ:**
- **ตรวจสอบ**ว่ามีข้อมูลบัญชีก่อนดำเนินการต่อ
- **เปลี่ยนเส้นทาง**ผู้ใช้ที่ไม่ได้รับการรับรองกลับไปยังหน้าล็อกอิน
- **อัปเดต**คำอธิบายบัญชีโดยใช้ฟังก์ชัน `updateElement` ที่นำกลับมาใช้ใหม่ได้
- **จัดรูปแบบ**ยอดคงเหลือให้แสดงทศนิยมสองตำแหน่งเสมอ
- **แสดง**สัญลักษณ์สกุลเงินที่เหมาะสม
> 💰 **การจัดรูปแบบเงิน**: เมธอด [`toFixed(2)`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) นั้นช่วยชีวิต! มันทำให้ยอดคงเหลือของคุณดูเหมือนเงินจริงเสมอ - "75.00" แทนที่จะเป็นแค่ "75" ผู้ใช้ของคุณจะชื่นชอบการเห็นการจัดรูปแบบสกุลเงินที่คุ้นเคย
#### ขั้นตอนที่ 3: ทำให้แน่ใจว่าแดชบอร์ดของคุณอัปเดต
เพื่อให้แน่ใจว่าแดชบอร์ดของคุณรีเฟรชด้วยข้อมูลปัจจุบันทุกครั้งที่มีคนเข้าชม เราจำเป็นต้องเชื่อมต่อกับระบบนำทางของคุณ หากคุณทำงานที่มอบหมายใน [บทเรียนที่ 1](../1-template-route/assignment.md) เสร็จแล้ว สิ่งนี้ควรรู้สึกคุ้นเคย หากยังไม่เสร็จ ไม่ต้องกังวล - นี่คือสิ่งที่คุณต้องการ:
เพิ่มสิ่งนี้ไปยังส่วนท้ายของฟังก์ชัน `updateRoute()` ของคุณ:
```javascript
if (typeof route.init === 'function') {
route.init();
}
```
จากนั้นอัปเดตเส้นทางของคุณเพื่อรวมการเริ่มต้นแดชบอร์ด:
```javascript
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard', init: updateDashboard }
};
```
**สิ่งที่การตั้งค่าที่ชาญฉลาดนี้ทำ:**
- ตรวจสอบว่าเส้นทางมีโค้ดเริ่มต้นพิเศษหรือไม่
- รันโค้ดนั้นโดยอัตโนมัติเมื่อเส้นทางโหลด
- ทำให้แน่ใจว่าแดชบอร์ดของคุณแสดงข้อมูลปัจจุบันเสมอ
- รักษาเหตุผลและการจัดระเบียบของตรรกะการนำทางของคุณ
#### การทดสอบแดชบอร์ดของคุณ
หลังจากดำเนินการเปลี่ยนแปลงเหล่านี้ ทดสอบแดชบอร์ดของคุณ:
1. **เข้าสู่ระบบ**ด้วยบัญชีทดสอบ
2. **ตรวจสอบ**ว่าคุณถูกเปลี่ยนเส้นทางไปยังแดชบอร์ด
3. **ตรวจสอบ**ว่าคำอธิบายบัญชี ยอดคงเหลือ และสกุลเงินแสดงผลอย่างถูกต้อง
4. **ลองออกจากระบบและเข้าสู่ระบบอีกครั้ง**เพื่อให้แน่ใจว่าข้อมูลรีเฟรชอย่างถูกต้อง
แดชบอร์ดของคุณควรแสดงข้อมูลบัญชีแบบไดนามิกที่อัปเดตตามข้อมูลของผู้ใช้ที่เข้าสู่ระบบ!
## การสร้างรายการธุรกรรมอัจฉริยะด้วยเทมเพลต
แทนที่จะสร้าง HTML สำหรับแต่ละธุรกรรมด้วยตนเอง เราจะใช้เทมเพลตเพื่อสร้างรูปแบบที่สม่ำเสมอโดยอัตโนมัติ เช่นเดียวกับส่วนประกอบมาตรฐานที่ใช้ในกระบวนการผลิตยานอวกาศ เทมเพลตช่วยให้ทุกแถวธุรกรรมมีโครงสร้างและลักษณะเหมือนกัน
เทคนิคนี้สามารถปรับขนาดได้อย่างมีประสิทธิภาพตั้งแต่ธุรกรรมไม่กี่รายการไปจนถึงหลายพันรายการ โดยยังคงรักษาประสิทธิภาพและการนำเสนอที่สม่ำเสมอ
```mermaid
flowchart LR
A[Transaction Data] --> B[HTML Template]
B --> C[Clone Template]
C --> D[Populate with Data]
D --> E[Add to DOM]
E --> F[Repeat for Each Transaction]
```
### ขั้นตอนที่ 1: สร้างเทมเพลตธุรกรรม
ก่อนอื่น เพิ่มเทมเพลตที่นำกลับมาใช้ใหม่สำหรับแถวธุรกรรมใน HTML `<body>` ของคุณ:
```html
<template id="transaction">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</template>
```
**ทำความเข้าใจเทมเพลต HTML:**
- **กำหนด**โครงสร้างสำหรับแถวตารางเดียว
- **ยังคง**มองไม่เห็นจนกว่าจะถูกโคลนและเติมข้อมูลด้วย JavaScript
- **รวม**สามเซลล์สำหรับวันที่ คำอธิบาย และจำนวนเงิน
- **ให้**รูปแบบที่นำกลับมาใช้ใหม่ได้สำหรับการจัดรูปแบบที่สม่ำเสมอ
### ขั้นตอนที่ 2: เตรียมตารางของคุณสำหรับเนื้อหาแบบไดนามิก
ถัดไป เพิ่ม `id` ให้กับส่วนตารางของคุณเพื่อให้ JavaScript สามารถกำหนดเป้าหมายได้ง่าย:
```html
<tbody id="transactions"></tbody>
```
**สิ่งที่สิ่งนี้ทำให้สำเร็จ:**
- **สร้าง**เป้าหมายที่ชัดเจนสำหรับการแทรกแถวธุรกรรม
- **แยก**โครงสร้างตารางออกจากเนื้อหาแบบไดนามิก
- **เปิดใช้งาน**การล้างและเติมข้อมูลธุรกรรมได้ง่าย
### ขั้นตอนที่ 3: สร้างฟังก์ชันโรงงานแถวธุรกรรม
ตอนนี้สร้างฟังก์ชันที่เปลี่ยนข้อมูลธุรกรรมเป็นองค์ประกอบ HTML:
```javascript
function createTransactionRow(transaction) {
const template = document.getElementById('transaction');
const transactionRow = template.content.cloneNode(true);
const tr = transactionRow.querySelector('tr');
tr.children[0].textContent = transaction.date;
tr.children[1].textContent = transaction.object;
tr.children[2].textContent = transaction.amount.toFixed(2);
return transactionRow;
}
```
**การแยกย่อยฟังก์ชันโรงงานนี้:**
- **ดึง**องค์ประกอบเทมเพลตโดย ID ของมัน
- **โคลน**เนื้อหาเทมเพลตเพื่อการจัดการที่ปลอดภัย
- **เลือก**แถวตารางภายในเนื้อหาโคลน
- **เติมข้อมูล**แต่ละเซลล์ด้วยข้อมูลธุรกรรม
- **จัดรูปแบบ**จำนวนเงินให้แสดงตำแหน่งทศนิยมที่เหมาะสม
- **ส่งคืน**แถวที่เสร็จสมบูรณ์พร้อมสำหรับการแทรก
### ขั้นตอนที่ 4: สร้างแถวธุรกรรมหลายแถวอย่างมีประสิทธิภาพ
เพิ่มโค้ดนี้ไปยังฟังก์ชัน `updateDashboard()` ของคุณเพื่อแสดงธุรกรรมทั้งหมด:
```javascript
const transactionsRows = document.createDocumentFragment();
for (const transaction of account.transactions) {
const transactionRow = createTransactionRow(transaction);
transactionsRows.appendChild(transactionRow);
}
updateElement('transactions', transactionsRows);
```
**ทำความเข้าใจวิธีการที่มีประสิทธิภาพนี้:**
- **สร้าง**เอกสาร fragment เพื่อจัดการการดำเนินการ DOM แบบกลุ่ม
**คำสั่ง:** สร้างฟังก์ชันการค้นหาสำหรับแอปธนาคารที่รวมถึง: 1) แบบฟอร์มการค้นหาที่มีช่องป้อนข้อมูลสำหรับช่วงวันที่ (จาก/ถึง), จำนวนเงินขั้นต่ำ/สูงสุด และคำสำคัญของคำอธิบายธุรกรรม, 2) ฟังก์ชัน `filterTransactions()` ที่กรองอาร์เรย์ account.transactions ตามเกณฑ์การค้นหา, 3) อัปเดตฟังก์ชัน `updateDashboard()` เพื่อแสดงผลลัพธ์ที่กรองแล้ว, และ 4) เพิ่มปุ่ม "ล้างตัวกรอง" เพื่อรีเซ็ตมุมมอง ใช้วิธีการอาร์เรย์ JavaScript สมัยใหม่ เช่น `filter()` และจัดการกรณีขอบสำหรับเกณฑ์การค้นหาที่ว่างเปล่า
เรียนรู้เพิ่มเติมเกี่ยวกับ [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) ที่นี่
## 🚀 ความท้าทาย
พร้อมที่จะยกระดับแอปธนาคารของคุณไปอีกขั้นหรือยัง? มาทำให้มันดูดีและใช้งานง่ายกันเถอะ นี่คือไอเดียบางส่วนเพื่อจุดประกายความคิดสร้างสรรค์ของคุณ:
**ทำให้สวยงาม**: เพิ่มการออกแบบ CSS เพื่อเปลี่ยนแดชบอร์ดที่ใช้งานได้ให้กลายเป็นสิ่งที่ดูน่าดึงดูดใจ คิดถึงเส้นที่สะอาดตา การเว้นระยะที่ดี และอาจมีแอนิเมชันเล็กน้อย
**ทำให้ตอบสนองได้ดี**: ลองใช้ [media queries](https://developer.mozilla.org/docs/Web/CSS/Media_Queries) เพื่อสร้าง [การออกแบบที่ตอบสนอง](https://developer.mozilla.org/docs/Web/Progressive_web_apps/Responsive/responsive_design_building_blocks) ที่ใช้งานได้ดีบนโทรศัพท์ แท็บเล็ต และเดสก์ท็อป ผู้ใช้ของคุณจะขอบคุณ!
**เพิ่มความน่าสนใจ**: พิจารณาการใช้สีเพื่อแยกประเภทธุรกรรม (สีเขียวสำหรับรายรับ สีแดงสำหรับรายจ่าย), เพิ่มไอคอน, หรือสร้างเอฟเฟกต์เมื่อวางเมาส์ที่ทำให้ส่วนติดต่อผู้ใช้ดูมีชีวิตชีวา
นี่คือตัวอย่างแดชบอร์ดที่ดูดีหลังจากการออกแบบ:
![ภาพหน้าจอของตัวอย่างผลลัพธ์ของแดชบอร์ดหลังการออกแบบ](../../../../translated_images/screen2.123c82a831a1d14ab2061994be2fa5de9cec1ce651047217d326d4773a6348e4.th.png)
ไม่จำเป็นต้องทำให้เหมือนตัวอย่างนี้เป๊ะ ๆ - ใช้มันเป็นแรงบันดาลใจและสร้างสรรค์ในแบบของคุณเอง!
## แบบทดสอบหลังการบรรยาย
[แบบทดสอบหลังการบรรยาย](https://ff-quizzes.netlify.app/web/quiz/46)
## งานที่ได้รับมอบหมาย
[ปรับปรุงและแสดงความคิดเห็นในโค้ดของคุณ](assignment.md)
---
**ข้อจำกัดความรับผิดชอบ**:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้