# בניית אפליקציית בנקאות חלק 3: שיטות לשליפת נתונים ושימוש בהם תחשבו על המחשב של האנטרפרייז ב"מסע בין כוכבים" - כשקפטן פיקארד מבקש מצב ספינה, המידע מופיע מיד בלי שהממשק כולו ייסגר וייבנה מחדש. הזרימה החלקה הזו של מידע היא בדיוק מה שאנחנו בונים כאן עם שליפת נתונים דינמית. כרגע, אפליקציית הבנקאות שלכם היא כמו עיתון מודפס - אינפורמטיבית אבל סטטית. אנחנו הולכים להפוך אותה למשהו יותר כמו מרכז הבקרה של נאס"א, שבו נתונים זורמים באופן רציף ומתעדכנים בזמן אמת בלי להפריע למהלך העבודה של המשתמש. תלמדו איך לתקשר עם שרתים בצורה אסינכרונית, להתמודד עם נתונים שמגיעים בזמנים שונים, ולהפוך מידע גולמי למשהו משמעותי עבור המשתמשים שלכם. זה ההבדל בין דמו לתוכנה מוכנה לייצור. ## ⚡ מה אפשר לעשות ב-5 הדקות הקרובות **מסלול התחלה מהירה למפתחים עסוקים** ```mermaid flowchart LR A[⚡ 5 minutes] --> B[Set up API server] B --> C[Test fetch with curl] C --> D[Create login function] D --> E[See data in action] ``` - **דקה 1-2**: הפעלו את שרת ה-API שלכם (`cd api && npm start`) ובדקו את החיבור - **דקה 3**: צרו פונקציה בסיסית `getAccount()` באמצעות fetch - **דקה 4**: חברו את טופס ההתחברות עם `action="javascript:login()"` - **דקה 5**: בדקו את ההתחברות וצפו בנתוני החשבון מופיעים בקונסול **פקודות בדיקה מהירה**: ```bash # Verify API is running curl http://localhost:5000/api # Test account data fetch curl http://localhost:5000/api/accounts/test ``` **למה זה חשוב**: תוך 5 דקות תראו את הקסם של שליפת נתונים אסינכרונית שמניעה כל אפליקציית ווב מודרנית. זה הבסיס שגורם לאפליקציות להרגיש תגובתיות וחיות. ## 🗺️ מסע הלמידה שלכם דרך אפליקציות ווב מבוססות נתונים ```mermaid journey title From Static Pages to Dynamic Applications section Understanding the Evolution Traditional page reloads: 3: You Discover AJAX/SPA benefits: 5: You Master Fetch API patterns: 7: You section Building Authentication Create login functions: 4: You Handle async operations: 6: You Manage user sessions: 8: You section Dynamic UI Updates Learn DOM manipulation: 5: You Build transaction displays: 7: You Create responsive dashboards: 9: You section Professional Patterns Template-based rendering: 6: You Error handling strategies: 7: You Performance optimization: 8: You ``` **יעד המסע שלכם**: בסוף השיעור הזה, תבינו איך אפליקציות ווב מודרניות שולפות, מעבדות ומציגות נתונים באופן דינמי, ויוצרות את חוויות המשתמש החלקות שאנו מצפים מאפליקציות מקצועיות. ## שאלון לפני השיעור [שאלון לפני השיעור](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 פעיל ומגיב - מוודאת שהאפליקציה שלכם יכולה להגיע לשרת (כמו בדיקת קשר רדיו לפני משימה) ## 🧠 סקירה של מערכת ניהול נתונים ```mermaid mindmap root((Data Management)) Authentication Flow Login Process Form Validation Credential Verification Session Management User State Global Account Object Navigation Guards Error Handling API Communication Fetch Patterns GET Requests POST Requests Error Responses Data Formats JSON Processing URL Encoding Response Parsing Dynamic UI Updates DOM Manipulation Safe Text Updates Element Creation Template Cloning User Experience Real-time Updates Error Messages Loading States Security Considerations XSS Prevention textContent Usage Input Sanitization Safe HTML Creation CORS Handling Cross-Origin Requests Header Configuration Development Setup ``` **עקרון מרכזי**: אפליקציות ווב מודרניות הן מערכות תזמור נתונים - הן מתאמות בין ממשקי משתמש, APIs של שרתים ומודלי אבטחת דפדפן כדי ליצור חוויות חלקות ותגובתיות. --- ## הבנת שליפת נתונים באפליקציות ווב מודרניות האופן שבו אפליקציות ווב מתמודדות עם נתונים השתנה באופן דרמטי במהלך שני העשורים האחרונים. הבנת האבולוציה הזו תעזור לכם להעריך מדוע טכניקות מודרניות כמו 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.he.png) **למה הגישה הזו הרגישה מסורבלת:** - כל לחיצה דרשה בנייה מחדש של כל העמוד מאפס - משתמשים הופרעו באמצע המחשבה על ידי הבהובים מעצבנים של העמוד - חיבור האינטרנט עבד שעות נוספות בהורדת אותו כותרת ותחתית שוב ושוב - אפליקציות הרגישו יותר כמו לעבור דרך ארון תיוק מאשר להשתמש בתוכנה ### אפליקציות עמוד יחיד מודרניות (SPA) AJAX (JavaScript ו-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.he.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 משתמש בהבטחות לקוד אסינכרוני נקי יותר ומטפל ב-JSON באופן טבעי. | תכונה | XMLHttpRequest | Fetch API | |-------|----------------|-----------| | **תחביר** | מבוסס קריאות מורכבות | מבוסס הבטחות נקי | | **טיפול ב-JSON** | נדרש ניתוח ידני | שיטה מובנית `.json()` | | **טיפול בשגיאות** | מידע שגיאות מוגבל | פרטי שגיאות מקיפים | | **תמיכה מודרנית** | תאימות למורשת | הבטחות ES6+ ו-async/await | > 💡 **תאימות דפדפנים**: חדשות טובות - 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`) כמאפיין של אלמנט הטופס. זה מספק דרך נקייה וקריאה לקבל נתוני טופס. #### שלב 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' }; } } ``` **הנה מה שהקוד הזה משיג:** - **משתמש** ב-API המודרני `fetch` כדי לבקש נתונים בצורה אסינכרונית - **בונה** כתובת URL של בקשת GET עם פרמטר שם המשתמש - **מיישם** `encodeURIComponent()` כדי לטפל בבטחה בתווים מיוחדים בכתובות URL - **ממיר** את התגובה לפורמט JSON לצורך מניפולציה קלה של נתונים - **מטפל** בשגיאות בצורה חלקה על ידי החזרת אובייקט שגיאה במקום קריסה > ⚠️ **הערת אבטחה**: הפונקציה `encodeURIComponent()` מטפלת בתווים מיוחדים בכתובות URL. כמו מערכות קידוד המשמשות בתקשורת ימית, היא מבטיחה שההודעה שלכם תגיע בדיוק כפי שהתכוונתם, ומונעת מתווים כמו "#" או "&" להתפרש בצורה שגויה. > **למה זה חשוב:** - מונע מתווים מיוחדים לשבור כתובות URL - מגן מפני התקפות מניפולציית URL - מבטיח שהשרת יקבל את הנתונים המיועדים - עוקב אחרי פרקטיקות קידוד מאובטחות #### הבנת בקשות HTTP GET הנה משהו שעשוי להפתיע אתכם: כשמשתמשים ב-`fetch` בלי אפשרויות נוספות, הוא יוצר אוטומטית בקשת [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET). זה מושלם למה שאנחנו עושים - מבקשים מהשרת "היי, אפשר לראות את נתוני החשבון של המשתמש הזה?" חשבו על בקשות GET כמו לבקש בנימוס להשאיל ספר מהספרייה - אתם מבקשים לראות משהו שכבר קיים. בקשות POST (שבהן השתמשנו להרשמה) הן יותר כמו להגיש ספר חדש להוספה לאוסף. | בקשת GET | בקשת POST | |----------|-----------| | **מטרה** | שליפת נתונים קיימים | שליחת נתונים חדשים לשרת | | **פרמטרים** | בנתיב URL/מחרוזת שאילתה | בגוף הבקשה | | **מטמון** | ניתן למטמון על ידי דפדפנים | לא בדרך כלל | | **אבטחה** | גלוי ב-URL/יומנים | מוסתר בגוף הבקשה | ```mermaid sequenceDiagram participant B as Browser participant S as Server Note over B,S: GET Request (Data Retrieval) B->>S: GET /api/accounts/test S-->>B: 200 OK + Account Data Note over B,S: POST Request (Data Submission) B->>S: POST /api/accounts + New Account Data S-->>B: 201 Created + Confirmation Note over B,S: Error Handling B->>S: GET /api/accounts/nonexistent S-->>B: 404 Not Found + Error Message ``` #### שלב 3: חיבור הכל יחד עכשיו לחלק המספק - בואו נחבר את פונקציית שליפת החשבון לתהליך ההתחברות. כאן הכל מתחבר: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; const data = await getAccount(user); if (data.error) { return console.log('loginError', data.error); } account = data; navigate('/dashboard'); } ``` הפונקציה הזו עוקבת אחרי רצף ברור: - שולפת את שם המשתמש מקלט הטופס - מבקשת את נתוני החשבון של המשתמש מהשרת - מטפלת בכל שגיאה שמתרחשת במהלך התהליך - שומרת את נתוני החשבון ומנווטת ללוח הבקרה במקרה של הצלחה > 🎯 **דפוס Async/Await**: מכיוון ש-`getAccount` היא פונקציה אסינכרונית, אנחנו משתמשים במילת המפתח `await` כדי להשהות את הביצוע עד שהשרת מגיב. זה מונע מהקוד להמשיך עם נתונים לא מוגדרים. #### שלב 4: יצירת מקום לנתונים שלכם האפליקציה שלכם צריכה מקום לשמור את מידע החשבון ברגע שהוא נטען. חשבו על זה כמו הזיכרון לטווח קצר של האפליקציה שלכם - מקום לשמור את נתוני המשתמש הנוכחי בהישג יד. הוסיפו את השורה הזו בראש קובץ `app.js` שלכם: ```javascript // This holds the current user's account data let account = null; ``` **למה אנחנו צריכים את זה:** - שומר את נתוני החשבון נגישים מכל מקום באפליקציה שלכם - התחלה עם `null` אומרת "אף אחד עדיין לא מחובר" - מתעדכן כשמישהו מתחבר או נרשם בהצלחה - פועל כמו מקור אמת יחיד - אין בלבול לגבי מי מחובר #### שלב 5: חיבור הטופס שלכם עכשיו בואו נחבר את פונקציית ההתחברות החדשה שלכם לטופס ה-HTML שלכם. עדכנו את תג הטופס שלכם כך: ```html
``` **מה השינוי הקטן הזה עושה:** - עוצר את הטופס מלעשות את ההתנהגות ברירת המחדל שלו "לטעון מחדש את כל העמוד" - קורא לפונקציית JavaScript המותאמת שלכם במקום - שומר על הכל חלק ודמוי אפליקציית עמוד יחיד - נותן לכם שליטה מלאה על מה שקורה כשמשתמשים לוחצים על "התחבר" #### שלב 6: שיפור פונקציית ההרשמה שלכם למען עקביות, עדכנו את פונקציית `register` שלכם גם לשמור נתוני חשבון ולנווט ללוח הבקרה: ```javascript // Add these lines at the end of your register function account = result; navigate('/dashboard'); ``` **השיפור הזה מספק:** - **מעבר חלק** מהרשמה ללוח הבקרה - **חוויית משתמש עקבית** בין זרימות ההתחברות וההרשמה - **גישה מיידית** לנתוני חשבון לאחר הרשמה מוצלחת #### בדיקת היישום שלכם ```mermaid flowchart TD A[User enters credentials] --> B[Login function called] B --> C[Fetch account data from server] C --> D{Data received successfully?} D -->|Yes| E[Store account data globally] D -->|No| F[Display error message] E --> G[Navigate to dashboard] F --> H[User stays on login page] ``` **זמן לקחת את זה לסיבוב:** 1. צרו חשבון חדש כדי לוודא שהכל עובד 2. נסו להתחבר עם אותם פרטי התחברות 3. הציצו בקונסול של הדפדפן שלכם (F12) אם משהו נראה לא תקין 4. ודאו שאתם מגיעים ללוח הבקרה לאחר התחברות מוצלחת אם משהו לא עובד, אל תיבהלו! רוב הבעיות הן תיקונים פשוטים כמו שגיאות כתיב או שכחה להפעיל את שרת ה-API. #### מילה מהירה על קסם בין-מקורי אולי אתם תוהים: "איך אפליקציית הווב שלי מדברת עם שרת ה-API הזה כשהם פועלים על פורטים שונים?" שאלה מצוינת! זה נוגע למשהו שכל מפתח ווב נתקל בו בסופו של דבר. > 🔒 **אבטחת בין-מקור**: דפדפנים אוכפים "מדיניות מקור זהה" כדי למנוע תקשורת לא מורשית בין דומיינים שונים. כמו מערכת הבדיקה בפנטגון, הם מאמתים שתקשורת מורשית לפני שמאפשרים העברת נתונים. > **בהגדרה שלנו:** - אפליקציית הווב שלכם פועלת על `localhost:3000` (שרת פיתוח) - שרת ה-API שלכם פועל על `localhost:5000` (שרת אחורי) - שרת ה-API כולל [כותרות CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) שמאשרות במפורש תקשורת מאפליקציית הווב שלכם הגדרה זו משקפת פיתוח בעולם האמיתי שבו אפליקציות פרונטאנד ובקאנד פועלות בדרך כלל על שרתים נפרדים. > 📚 **למדו עוד**: צללו עמוק יותר ל-APIs ושליפת נתונים עם [מודול Microsoft Learn המקיף על APIs](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## הבאת הנתונים שלכם לחיים ב-HTML עכשיו נעשה את הנתונים שנשלפו גלויים למשתמשים דרך מניפולציה של מניפולציה ב-DOM היא הטכניקה שהופכת דפי אינטרנט סטטיים לאפליקציות דינמיות שמעדכנות את התוכן שלהן בהתאם לאינטראקציות המשתמש ולתגובות מהשרת. ### בחירת הכלי הנכון למשימה כשמדובר בעדכון ה-HTML שלך באמצעות JavaScript, יש לך כמה אפשרויות. תחשוב על זה כמו על כלים שונים בארגז כלים - כל אחד מהם מושלם למשימות ספציפיות: | שיטה | למה היא מצוינת | מתי להשתמש בה | רמת בטיחות | |------|----------------|----------------|------------| | `textContent` | הצגת נתוני משתמש בצורה בטוחה | בכל פעם שאתה מציג טקסט | ✅ יציב לחלוטין | | `createElement()` + `append()` | בניית מבנים מורכבים | יצירת חלקים חדשים/רשימות | ✅ חסין | | `innerHTML` | הגדרת תוכן HTML | ⚠️ נסה להימנע מזה | ❌ מסוכן | #### הדרך הבטוחה להציג טקסט: textContent המאפיין [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) הוא החבר הכי טוב שלך כשמדובר בהצגת נתוני משתמש. זה כמו שיש שומר סף לדף האינטרנט שלך - שום דבר מזיק לא עובר: ```javascript // The safe, reliable way to update text const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **יתרונות של textContent:** - מתייחס לכל דבר כטקסט רגיל (מונע ביצוע סקריפטים) - מנקה תוכן קיים באופן אוטומטי - יעיל לעדכוני טקסט פשוטים - מספק אבטחה מובנית נגד תוכן מזיק #### יצירת אלמנטים HTML דינמיים לתוכן מורכב יותר, שלב את [`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:** - מבצע כל תג `