ToCode
Kanalga Telegram’da o‘tish
טיפים קצרים למתכנתים מאת ינון פרק
Ko'proq ko'rsatish1 420
Obunachilar
Ma'lumot yo'q24 soatlar
-17 kunlar
Ma'lumot yo'q30 kunlar
Postlar arxiv
1 421
# כמה הערות על בדיקות בסביבת Micro Services
הקשבתי השבוע לפרק הזה מתוך עושים תוכנה בנושא בדיקות ל Micro Services. אני מסכם כאן כמה הערות אחרי ההאזנה, ובאמת שאם הנושא מעניין אתכם שווה להקשיב לפרק גם:
1. בדיקות End To End בסביבת Micro Services הן הרבה יותר יקרות מאשר בסביבת מונולית (ולא שבמונולית הן היו זולות). עיקר העלות הוא הקושי להעלות מערכת מלאה ויציבה התואמת למה שיש בגירסת הפרודקשן.
2. למרות המחיר העצום, אם נצליח להקים תשתית של בדיקות End To End אלה הולכות להיות הבדיקות שיתנו לנו את הביטחון הגדול ביותר שהמערכת אכן עובדת. פה יש כל מיני טכניקות בתוך המשפחה שנקראת Testing In Production, כמו למשל לשכפל את סביבת הפרודקשן ולבדוק בעותק, או אפילו לייצר סביבה מקבילה (Shadow) לפרודקשן ולבדוק שם.
3. בעיות חדשות של E2E Tests לסביבת Micro Services: אין מי שיתחזק אותן, כי כישלון בבדיקה הוא תמיד חוצה צוותים; ושינויים מהירים במערכת מביאים לזה שהבדיקות מאוד לא יציבות. לכן בדיקות E2E יוצרות תלות בין צוותי, וזה בדיוק מה שרצינו לברוח ממנו כשהלכנו לכתוב Micro Services.
4. בגלל המחיר הגבוה של בדיקות E2E אנחנו מחפשים פיתרונות יותר "קלים". הפיתרון המרכזי שמדברים עליו הוא Component Tests, שאלה בדיקות שמתמקדות בסרביס ספציפי ובודקות שהוא פועל לפי הממשק שהוא מתחייב עליו. זה יהיה סוג הבדיקות המרכזי במערכת.
5. בכתיבת Component Tests לרוב נבצע Mock לסרביסים האחרים. פריימוורק בשם Pact מאפשר בצורה אוטומטית ליצור מתוך המוקים האלה מסמכי בדיקות עבור כותבי הסרביסים האחרים (הספקים שלנו) כדי שהם יוכלו להיות רגועים שהם לא שוברים לנו את הסרביס. בדיקות כאלה נקראות Contract Tests, ומסתבר שגם הן די יקרות לתחזוקה, אבל עדיין פחות יקרות מ E2E.
6. ברוב צוותי התוכנה סט בדיקות ה E2E נכשל מדי פעם בצורה אקראית ואין מספיק כח אדם כדי לתחזק כמו שצריך בדיקות E2E אמינות.
7. אין פיתרונות קסם. ככל שאנחנו רוצים להתקדם יותר מהר בפיתוח כך זה יבוא על חשבון הביטחון במוצר שלנו. בהרבה מוצרים באמצעות ניהול סיכונים טוב נעדיף לא לכוון למדיניות של אפס באגים אלא למדיניות של מספיק בדיקות, מעט באגים ויכולת זיהוי ותיקון מהירה של התקלות.
1 421
# הזדמנות אחרונה
די בטוח שהיא לא האחרונה, וכנראה שהיא גם לא היתה הזדמנות.
גם 13 שנה אחרי השקת ה App Store אנשים עדיין כותבים אפליקציות ועדיין מרוויחים לא רע מזה. אפילו אם תתחילי היום ללמוד Swift, עדיין לא פספסת את ההזדמנות האחרונה לכתוב אפליקציות.
ואין ספק ש JavaScript עברה הרבה גלגולים ושינויים מאז הופעתה ב 1995 על במת ההיסטוריה, וזה לא עוצר אינספור אנשים להתחיל ללמוד אותה, כל שנה מחדש.
המחשבה שהיית צריך ללמוד Selenium כשהיה לך זמן ולפני שהתחלת את העבודה הנוכחית בתור בודק תוכנה ועכשיו פספסת את ההזדמנות אולי נותנת סוג של נחמה, אבל היא לא אפקטיבית ולא נכונה. הרבה מאוד בודקי תוכנה מתחילים ללמוד סלניום דווקא תוך כדי עבודה ואפילו מגלים שיותר קל ללמוד כשלא צריך לדאוג למשכורת הבאה.
אני מאוד בעד בזמן אמת להסתכל על כל הזדמנות כאילו היא האחרונה; להתכונן לכל ראיון עבודה כאילו הוא האחרון; להשקיע בכל פרויקט כאילו זה הלקוח האחרון שאי פעם יפנה אליך וזאת ההזדמנות האחרונה להשאיר רושם טוב. אבל בדיעבד? חבל על המאמץ. ההזדמנות הבאה מתחילה היום בבוקר, והיא הרבה יותר מעניינת.
1 421
1. כתבו קומפוננטה בשם FilteredList שמציגה רשימה של פריטים שקיבלה מבחוץ (באמצעות prop) ותיבת חיפוש. הקלדה של טקסט בתיבת החיפוש מצמצמת את הפריטים שמופיעים על המסך ומראה רק את אלה שמתאימים למילה שהוקלדה בתיבת החיפוש.
2. כתבו קומפוננטה בשם RandomOrder שמציגה רשימה של פריטים שקיבלה מבחוץ וכפתור Shuffle. לחיצה על כפתור Shuffle מערבבת את הפריטים ומציגה אותם בסדר חדש.
3. כתבו קומפוננטה בשם SelectableList המציגה רשימה של פריטים שקיבלה מבחוץ וליד כל פריט מציגה Checkbox, וליד הרשימה כפתור Delete. משתמשים יוכלו לבחור מספר פריטים וללחוץ Delete כדי למחוק אותם. הוסיפו גם כפתור Reset שמחזיר את כל הפריטים שנמחקו.
4. הוסיפו לקומפוננטה SelectableList כפתור Shuffle שיערבב את סדר הפריטים. וודאו שאתם יכולים לסמן פריטים, לערבב, ומה שסימנתם נשאר מסומן.
5. כתבו קומפוננטה בשם SortableTable המציגה מידע בצורה של טבלה עם אפשרות למיין את המידע לפי העמודות. לדוגמה אם המידע שלי הוא:
const data = [
['id', 'Name', 'Country', 'Email'],
[0, 'dan', 'Israel', 'dan@gmail.com'],
[1, 'dana', 'Israel', 'dana@gmail.com'],
[2, 'anna', 'Israel', 'anna@gmail.com'],
[3, 'zina', 'UK', 'zina@gmail.com'],
];
נרצה להציג טבלה עם 4 עמודות, שורת כותרת ו-4 שורות לפריטים. לחיצה על עמודה מסדרת את השורות מהקטן לגדול לפי הערך באותה עמודה. לחיצה שניה על אותה עמודה מסדרת במיון הפוך (מהגדול לקטן) את השורות בטבלה שוב לפי הערך של העמודה שנלחצה.1 421
</template>אפשר להוסיף v-for לכל אלמנט בטמפלייט מלבד האלמנט החיצוני ביותר, וזה פשוט גורם ל vue לשכפל את האלמנט לפי הלולאה שנכתוב. דרך נוספת לקבל דינמיות היא להציג או להסתיר אלמנט מסוים, ואת זה אנחנו עושים עם
v-if, v-else ו v-else-if. הקומפוננטה הבאה תציג את המילה Happy אם הטקסט שכתבתם בתיבה מתחיל באות קטנה, ו Sad אם הטקסט מתחיל באות גדולה:
<template>
<div>
<label>
Type Something
<input type="text" v-model="text" />
</label>
<div>
<p>
My Mood today is:
<span class="mood-happy" v-if="mood(text) === 'Happy'">Happy</span>
<span class="mood-sad" v-else-if="mood(text) === 'Sad'">Sad</span>
</p>
</div>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
text: "",
};
},
methods: {
mood(text) {
if (text.length === 0) {
return "Sad";
} else if (text[0].toUpperCase() === text[0]) {
return "Happy";
} else {
return "Sad";
}
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.mood-happy {
color: pink;
}
.mood-sad {
color: blue;
}
</style>
החלק הדינמי בתבנית הוא שני ה span-ים עם המאפיינים v-if ו v-else-if, שיוצגו רק אם התנאים שלהם מתקיימים.
אתם מוזמנים לקרוא את כל הפרטים על v-if בתיעוד בקישור:
https://v3.vuejs.org/guide/conditional.html
ואת כל הפרטים על v-for בתיעוד בקישור:
https://v3.vuejs.org/guide/list.html
## גישה 2: שימוש ב Render Functions
גישה שניה לכתיבת קומפוננטות דינמיות היא לוותר לגמרי על בלוק ה template ולהחליף אותו בפונקציה בשם render שמחזירה את עץ הקומפוננטות הוירטואלי בצורה דינמית.
הנה דוגמה לקומפוננטה סופר פשוטה שמשתמשת בגישה זו:
<script>
import { h } from "vue";
export default {
name: "HelloWorld",
render() {
return h("p", "Hello World");
},
};
</script>
קומפוננטות כאלה אנחנו אפילו לא חייבים לכתוב בקובץ עם סיומת vue ויכולים לכתוב אותן בקובץ עם סיומת js רגיל.
הפונקציה render מחזירה "עץ קומפוננטות" שנבנה באמצעות הפונקציה h של vue. הפונקציה h מקבלת שלושה פרמטרים: שם האלמנט, הילדים ומאפייני האלמנט, ובונה את העץ. הנה דוגמה יותר מתוחכמת לשימוש בה, הפעם עם לולאה:
<script>
import { h } from "vue";
export default {
name: "HelloWorld",
render() {
return h(
"ul",
["one", "two", "three"].map((text) => h("li", { key: text }, text))
);
},
};
</script>
הפונקציה h אולי קצת מסורבלת, אבל עם פלאגין מתאים ל Babel אפשר להפוך את כל הכתיב הזה ל JSX שמרגיש ממש בבית למתכנתי ריאקט, כלומר את אותה קומפוננטה אפשר יהיה לכתוב כך אחרי התקנת הפלאגין:
export default {
name: "HelloWorld",
render() {
return (
<ul>
{["one", "two", "three"].map(text => (
<li key={text}>{text}</li>
))}
</ul>
);
},
};
ברוב המקרים ב Vue נשתמש בגישת הטמפלייטס לרוב הקומפוננטות שלנו, אבל אם נגלה שקומפוננטה מסוימת צריכה יותר גמישות אז תמיד אפשר לעבור לכתוב Render Function.
## סיכום
הגישה של Vue לאלמנטים דינמיים בתוך התבנית מתבססת על מאפיינים מיוחדים שאנחנו יכולים להוסיף לאלמנטים שיגרמו להם להופיע, לא להופיע או להופיע מספר פעמים. היתרון בגישה זו הוא שאחרי לימוד קצר והבנה של מקרי הקצה רוב מתכנתי ויו יצליחו להגיע לקוד ויו חדש ולמצוא בקלות את הידיים והרגליים.
החיסרון בגישה זו הוא שהיא לא מעודדת אותנו להמציא מחדש את הגלגל ולא נותנת לנו כלים לכתוב לבד את המנגנונים הדינמיים. בגישה של Vue, מי שמספיק מתקדם כדי לרצות לכתוב את המנגנונים האלה לבד עדיף שישתמש ב Render Function. הטמפלייט נועד להקל על העבודה ולתת לאנשים ממשק נגיש ומהיר יותר לבניית הקוד.
## תרגילים
אתם עוד פה? מצוין! כמו בחלקים קודמים של המדריך גם הפעם אני רוצה להציע מספר תרגילים שיעזרו לכם לוודא שאתם מבינים את כל מה שקרה פה:1 421
# מדריך Vue למתחילים - חלק 3 - תבניות דינמיות
ויו היא פריימוורק לפיתוח יישומי Front End מבוססי קומפוננטות. פוסט זה הוא השלישי בסידרת "מדריך Vue למתחילים" שאני מקווה שיעזור לכם לקחת את הצעדים הראשונים עם הפריימוורק ולקבל הבנה טובה של העקרונות שלה. עד עכשיו פורסמו במדריך:
1. חלק 1 - קומפוננטה ראשונה ב Vue
2. חלק 2 - תקשורת בין קומפוננטות
## מה אנחנו רוצים לבנות
אחרי שאנחנו כבר יודעים לכתוב קומפוננטות ואפילו אפליקציה מלאה המורכבת ממספר קומפוננטות יהיה מעניין להתמקד בכתיב ה Template של ויו ולראות איך אפשר להפוך אותו לדינמי. תבנית דינמית היא תבנית בה אנחנו לא יודעים מראש בדיוק מה יהיו האלמנטים השונים שלה. לדוגמה:
1. תבנית המציגה רשימת מטלות לביצוע, כשהמטלות עצמן מגיעות משרת או מפעולות של משתמש.
2. תבנית של קומפוננטה שלפעמים מציגה כפתור Login ולפעמים כפתור Logout, תלוי אם המשתמש מחובר למערכת.
בשני המקרים, כמו גם במקרים רבים נוספים שאפשר להעלות על הדעת, יש היבט דינמי לתבנית. אני לא יכול פשוט להתחיל לכתוב בלוק template ולכתוב בתוכו את כל האלמנטים שיהיו בה, כי בזמן כתיבת הטמפלייט אני עדיין לא יודע מה יהיה המבנה המדויק.
## מה לא עושים
מתכנתים שמגיעים מפריימוורקס אחרים, ובמיוחד מריאקט, עשויים לחשוב שאין פה באמת בעיה. הרי אנחנו זוכרים ש Vue מאפשר דינמיות מסוימת בתוך תבנית והקוד הבא הוא קוד תבנית תקין לגמרי:
<p>Hello {{ name }}</p>
אז ניסיון ראשון לייצר דינמיות יהיה לכתוב את הקוד הדינמי בתוך השפמים, לדוגמה משהו כזה:
<template>
<ul>
{{
['one', 'two', 'three'].map(text => <li>{{text}}</li>)
}}
</ul>
</template>
אבל ויו לא משתף פעולה. הודעת השגיאה שתופיעה היא:
VueCompilerError: Invalid end tag.
at /src/components/HelloWorld.vue:4:53
2 | <ul>
3 | {{
4 | ['one', 'two', 'three'].map(text => <li>{{text}}</li>)
| ^
5 | }}
6 | </ul>
הסיבה שזה לא עובד היא אולי טכנית, אבל מעבר להיבטים הטכניים שלה יש פה עניין עקרוני של ויו: הגישה של Vue היא שעדיף לתת בתוך הפריימוורק דרך לאנשים לעשות את מה שהם רוצים, במקום לתת לאנשים את הכלים לבנות בעצמם את הדברים שהם רוצים. במילים אחרות, איפה שריאקט אומר "תריצו איזה קוד JavaScript שאתם רוצים בתוך תבניות, ותמצאו את הדרך בעצמכם לכתוב לולאות ותנאים", ויו יגיד "אני אתן לכם דרך נקיה לכתוב לולאות או תנאים בתוך התבניות כדי שכל מתכנתי ויו ישתמשו באותו מנגנון".
למרות שזאת הגישה המרכזית ב Vue, יש גם פתח מילוט שנקרא Render Functions שמאפשר לנו כן לבנות את כל המנגנון לבד ונדבר עליו בסוף המדריך.
## גישה 1: שימוש ב Directives
הגישה הראשונה של Vue להכנסת דינמיות לתוך התבניות היא שימוש במילות קוד מיוחדות של Vue:
1. ההוראה v-for מייצרת לולאה
2. ההוראה v-if מייצרת תנאי
3. ההוראות v-else ו v-else-if
בואו נראה מה התפקיד של כל אחת מהן ואיך להשתמש בה. נתחיל עם v-for. אם אנחנו רוצים לייצר לולאה בתוך תבנית, נוסיף מאפיין v-for לאלמנט שאנחנו רוצים לשכפל. הערך של המאפיין יהיה ביטוי מהצורה x in y או (x, index) in y או x in N כאשר x הוא שם של משתנה רץ ו y הוא שם של מערך. בצורה השניה index הוא שם של משתנה שמקבל את אינדקס האיבר, ובצורה השלישית N הוא מספר והלולאה רצה N פעמים.
את אותה תבנית שלא הצלחתי לכתוב קודם אפשר לכתוב בקלות עם v-if בצורה הבאה:
<template>
<ul v-for="text in ['one', 'two', 'three']" :key="text">
<li>{{ text }}</li>
</ul>
</template>
עכשיו צריך לעצור רגע על המאפיין שהוספתי :key. תפקידו לעזור ל vue להבין אם אלמנטים שינו מקום בין הצגה אחת של המידע לזו שאחריה, והוא צריך להחזיק ערך ייחודי שמתאים לאלמנט הנוכחי בלולאה. אם אתם בטוחים שאלמנטים אף פעם לא ישנו מקום (למשל כי אין לכם פונקציית מיון בתוכנית) תוכלו להשתמש באינדקס, אם הערכים ייחודיים כמו בדוגמה שאני כתבתי תוכלו להשתמש בערך עצמו, ואם יש לכם אוביקטים אז אולי יש לכל אוביקט שדה id. בכל מקרה זאת אחריות שלכם למצוא מזהה ייחודי לכל פריט שאתם רוצים להציג ברשימה ולהעביר אותו למאפיין key.
הנה לולאה נוספת הפעם שתציג את כל המספרים מ-1 עד 100:
<template>
<div>
<p v-for="number in 100" :key="number">{{number}}</p>
</div>1 421
# שתי תכונות ששווה להשקיע בהן
שתי התכונות הבאות מאפיינות הרבה מהמתכנתים הטובים שפגשתי:
1. מתכנתים טובים כותבים רק קוד שהם מבינים עד הסוף את המשמעויות שלו, ומוכנים להשקיע את הזמן וללמוד לעומק נושאים לפני שמתקדמים את הצעד הבא.
2. מתכנתים טובים מוכנים להתקדם צעד אחרי צעד, גם בלי לראות את הסוף.
שתיהן קשות. הראשונה כי הרשת מלאה בקיצורי דרך ובעבודה על מערכת יש המון מקומות שאפשר להעתיק מהם כדי לסיים את המשימה. הבנה מעמיקה של עולם התוכן הרבה פעמים נראית כמו בונוס. והשניה כי אי וודאות יוצרת פחד והפחד משתק.
אפשר ושווה להתאמן על זה.
1 421
# המשבר השני
משבר המוטיבציה הראשון הוא קל - זה המשבר שקורה לפני או ממש בתחילת תהליך הלימוד, כשאתה עדיין פוחד מכל הדברים הרעים שהולכים לקרות ומהשינוי שהולך להגיע. זה הזמן שאנחנו מורחים לפני שמתחילים לעשות ספורט, או ביטול האימון בשבוע השני של התוכנית בגלל שטות כזאת או אחרת.
משבר המוטיבציה השני הוא כבר סיפור אחר כי אתה לא מצפה לו. המשבר הזה קורה שלושה חודשים או שנה לתוך הפרויקט. והוא יכול לתפוס מתכנתים גם אחרי שנתיים או שלוש של עבודה בתחום.
כשאתה רק מתחיל פרויקט אין לך ממש מושג איך תרגיש איתו ואיך הפרויקט ישפיע לך על החיים. יש חלום, זה בטוח, אבל החלום הזה מצויר בקווים מאוד כלליים, משהו כמו "אני רוצה להיכנס לכושר", "אני רוצה להרגיש טוב יותר במהלך היום" או "אני רוצה להיראות טוב יותר".
ואז מתחילים לעבוד ובהתחלה זה קשה כי שום דבר לא מצליח ואי אפשר כמעט לדמיין איך זה ירגיש כשהכל יעבוד טוב, אבל בשלב מסוים דברים כן מתחילים להצליח: פתאום אתה מצליח לסיים ריצה בלי להתמוטט אחרי, או מצליח לכתוב תוכנית שלמה שגם עובדת. וכשזה חוזר על עצמו עוד שבוע ועוד שבוע אפשר להתחיל לדמיין מה זה אומר "אורח חיים ספורטיבי" או "חיים בתור מתכנת" או "חיים בתור מוזיקאי". פתאום במכה אחת אפשר לראות ולהבין את כל ההשקעה שעוד נדרשת ושעוד תידרש לעד כדי להגשים את החלום, וההבנה הזאת יוצרת משבר מוטיבציה רציני.
הבעיה עם המשבר השני היא שלכל דבר בחיים יש מחיר, וגם אם תעזוב את הפרויקט עכשיו אחרי שגילית את המחיר האמיתי שלו אף אחד לא מבטיח לך שהפרויקט הבא יתנהג אחרת. למעשה רוב הסיכויים שגם בפרויקט הבא תגיע למשבר המוטיבציה השני, ובדיוק באותה נקודה. מצד שני לפעמים ההבנה האמיתית של הפרויקט גם חושפת משהו לגבי היחס שלך אליו ומגלה שעדיף לברוח.
שתי דוגמאות קלות ומסקנה -
1. מתכנת שלמד 3 שנים ואחרי זה התאמץ ומצא עבודה, אבל אחרי שנתיים של עבודה מרגיש שהחיים בתור מתכנת לא מתאימים לו ובעצם היה רוצה לעשות משהו אחר לגמרי.
2. סטארט-אפיסט שבונה MVP למוצר ואחרי חצי שנה של עבודה מבין שייקח לפחות עוד כמה חודשים עד שיוכל להגיע למשהו מספיק טוב בשביל לגייס עבורו כסף, ומרגיש שאין לו כוחות להמשיך.
שני המקרים מתארים משבר מוטיבציה שני אבל ההבדל ביניהם מאוד בולט. לראשון נרצה להגיד להתעלם מהעלות השקועה, את השנים האבודות הוא כבר לא יקבל חזרה, ולחפש עבודה אחרת. לשני נרצה להגיד שכדאי למצוא דרך להמשיך לעבוד, גם אם בקצב יותר נמוך ובשילוב עבודה אחרת, כי החלום עדיין לא עזב אותו.
במקרה הכללי, משבר המוטיבציה השני הוא ההזדמנות לזהות עד כמה הפרויקט היה חשוב לנו ועד כמה הוא חשוב לנו עדיין. כשהפרויקט חשוב שווה להסתכל למשבר טוב טוב בעיניים, לחייך ולהמשיך לנסוע קדימה. כשהמחשבה על הסוף רק מגבירה את הבחילה, זה הזמן לברוח.
1 421
3. אפשרו לקומפוננטת הטופס להעביר וולידציות שונות פנימה לקומפוננטות השדות בטפסים - למשל וולידציה שאומרת שהשדה חייב לקבל ערך, או וולידציה שאומרת שהשדה צריך להיות באורך מסוים.
4. הוסיפו וולידציה שתוודא שמידע בשדה מסוים זהה למידע בשדה אחר (לדוגמה עבור שדה Email Validation). איזה שינויים תצטרכו לעשות בקוד בשביל לבנות וולידציה כזו?
5. הוסיפו בראש הטופס כיתוב שמראה כמה שגיאות יש בטופס, כלומר כמה שדות לא עוברים וולידציה.
6. קראו את התיעוד על ספריית Formulate ובנו באמצעותה את הטופס עם הוולידציות. השוו לקוד שאתם בניתם. מיטיבי לכת מוזמנים להוסיף פיצ'רים שאהבתם מתוך הספריה.
1 421
בקישור הבא תמצאו את דוגמת הקוד בתוך קודסנדבוקס כדי שתוכלו לשחק בעצמכם עם העברת props לקומפוננטה:
https://codesandbox.io/s/winter-tdd-xglp3.
## שליחת אירועים
מנגנון תקשורת שני שחשוב להכיר הוא התקשורת בכיוון ההפוך - מקומפוננטה פנימית אל הקומפוננטה שמכילה אותה. אם Property הם הדרך שלנו להעביר מידע מבחוץ פנימה לקומפוננטה, אז אירועים או Events, הם הדרך שלנו להוציא מידע מקומפוננטה כלפי מעלה בעץ. נשים בצד את הדוגמה של כפתורי הניווט ונעבור לדוגמה עם כפתורים אמיתיים: מאיזושהי סיבה החלטתם לכתוב אפליקציה שמראה 3 כפתורים וליד כל כפתור מונה שמראה כמה פעמים לחצו עליו. אבל זה לא נגמר פה, ואנחנו גם רוצים שמעל כל הכפתורים יהיה כתוב כמה לחיצות סך הכל נלחצו בכל שלושת הכפתורים.
דרך אחת לגשת לזה היא לבקש מקומפוננטת הכפתור שתודיע לנו כל פעם שלוחצים עליה, כדי שהקומפוננטה הראשית תוכל לעדכן איזושהו מונה גלובאלי. כלומר להשתמש בטמפלייט ראשי שנראה בערך כך:
<template>
<p>Total Clicks: {{ totalClicks }}</p>
<Counter @click="addClicks" />
<Counter @click="addClicks" />
<Counter @click="addClicks" />
</template>
אנחנו יודעים שלאלמנט מסוג button אפשר להעביר מאפיין @click כדי לגרום לו להפעיל פונקציה שלנו כל פעם שלוחצים עליו, אבל איך אפשר לעשות את אותו טריק עם קומפוננטה שלנו? מסתבר שזה די פשוט:
1. בקומפוננטה שלנו אני מגדיר שדה בשם emits ושם כותב את כל האירועים שהקומפוננטה מדווחת עליהם.
2. כשצריך לדווח על אירוע אני מפעיל את הפונקציה this.$emit, מעביר לה את שם האירוע ואת הפרמטרים שמצורפים אליו.
במקרה של Counter הקוד יראה בערך כך:
export default {
emits: ["click"],
data() {
return {
count: 0,
};
},
methods: {
inc() {
this.count += 1;
this.$emit("click", this.count);
},
},
};
אתם יכולים לבחור כל שם לאירוע שלכם, ולהגדיר כמה אירועים שאתם רוצים. בזכות סימן ה @ לפני שם המאפיין בטמפלייט, ויו יודע שהערך הוא פונקציה ויודע לחבר אותה לאירוע שכתבתם.
זה המקום לשאול: למה צריך שני מנגנונים שונים להעברת מידע, לפי כיוון המידע? למה כשמעבירים מידע מקומפוננטה חיצונית לקומפוננטה פנימית אנחנו מעבירים ערך באמצעות Props, אבל כשרוצים להעביר מידע מקומפוננטה פנימית לחיצונית אנחנו צריכים להפעיל פונקציה? התשובה לא נובעת ממגבלה טכנית אלא מבחירת ארכיטקטורה. העברת המידע ב Vue מ"למעלה למטה" מכריחה אותנו לחשוב לגבי כל פיסת מידע באפליקציה מי הקומפוננטה שאחראית על מידע זה, ומכריחה אותנו לשמור מידע משותף לכמה קומפוננטות בקומפוננטה עליונה יותר בעץ. מבנה כזה מאפשר יותר בקלות לזהות מהו המידע של היישום ולעקוב אחריו כדי למצוא באגים בתוכנית.
מוזמנים לחטט בקוד המלא בקישור: https://codesandbox.io/s/elastic-dawn-ch4vb.
## מנגנונים נוספים ששווה להכיר
ב Vue קיימים עוד שלושה מנגנונים להעברת מידע בין קומפוננטות עליהם לא כתבתי בפרק זה של המדריך:
1. מנגנון אחד פשוט הוא העברת מאפייני HTML שפשוט יודבקו לאלמנט הראשי בקומפוננטה הפנימית. אתם יכולים לנסות להעביר כל מאפיין שתרצו מקומפוננטה עליונה לאלה שבתוכה ותראו ב Inspect Element שהמאפיינים הודבקו לאלמנט הראשי בקומפוננטה הפנימית. מנגנון זה עוזר כשרוצים להעביר דברים שיש להם השפעה ב HTML למשל id או class.
2. מנגנון שני נקרא provide/inject והוא מאפשר להעביר מידע בין שתי קומפוננטות הרחוקות אחת מהשניה בעץ הקומפוננטות. באופן רגיל אם יש קומפוננטה A ובתוכה קומפוננטה B ובתוכה קומפוננטה C ובתוכה קומפוננטה D, אז בשביל להעביר מידע מ A ל D צריך להעביר אותו קודם מ A ל B, ואז מ B ל C ואז מ C ל D. מנגנון provide/inject מאפשר "לדלג" על הקומפוננטות שבאמצע ולשלוח מידע מקצה אחד של העץ לקצה שני שלו.
3. מנגנון שלישי נקרא Slots והוא מאפשר לקומפוננטה לקבל קומפוננטות אחרות כקלט באמצעות העברת "ילדים" בתוך התבנית.
אתם יכולים לקרוא על שלושת המנגנונים בתיעוד של Vue ולפחות על השניים האחרונים אני כנראה אכתוב בפרקים הבאים של מדריך זה.
## תרגילים
אתם עוד פה? מעולה! הנה כמה רעיונות לתרגולים שתוכלו לנסות עם הדברים החדשים שלמדתם על Vue:
1. כתבו קומפוננטה לייצוג שדה מידע בטופס - הקומפוננטה תקבל טקסט עבור ה label ושם של שדה המידע ותציג תיבת קלט עם מאפיין name שמתאים לשם שהתקבל ו label עם הטקסט שהתקבל.
2. כתבו קומפוננטה של טופס שמציגה מספר שדות תוך שימוש בקומפוננטת השדה בטופס שכתבתם.1 421
# מדריך Vue למתחילים - פרק 2 - תקשורת בין קומפוננטות באותו עץ
בפרק הראשון של המדריך למדנו את העקרונות המרכזיים של Vue ואיך לכתוב קומפוננטות פשוטות. אפליקציית Vue מלאה מורכבת ממספר קומפוננטות ולכן בפרק זה נדבר על הקשר בין מספר קומפוננטות ב Vue ועל העברת המידע ביניהן.
## העברת props
הרעיון הראשון שצריך לקחת כשאנחנו בונים אפליקציית Vue הוא שאנחנו רוצים לארגן את כל האפליקציה שלנו בתור אוסף של קומפוננטות, שנקרא גם עץ של קומפוננטות (Component Tree). כל דף אינטרנט אפשר לחלק לקומפוננטות והרבה פעמים אנחנו נמצא קומפוננטות מסוימות מופיעות יותר מפעם אחת בעמוד. בעמוד הבית של גוגל לדוגמה אפשר לראות בשורה העליונה את כפתורי הניווט Gmail, Images, תפריט ו Sign In; לאחר מכן באמצע העמוד יש תמונה ומתחתיה תיבת חיפוש; בהמשך העמוד שני הכפתורים Google Search ו I'm Feeling Lucky; המשך לבחירת שפה ולמטה אזור ה Footer. בשביל לבנות מהעמוד שלהם עץ קומפוננטות כל מה שצריך הוא להסתכל ולהגדיר:
1. קומפוננטה של שורת ניווט
2. בתוכה תופיע פעמיים קומפוננטה של כפתור ניווט, פעם אחת עם הטקסט Gmail ופעם שניה עם הטקסט Images
3. לידן קומפוננטה נוספת של תפריט נפתח
4. ואז שוב קומפוננטה של כפתור ניווט הפעם כפתור Primary עם הטקסט Sign In
5. קומפוננטה של תמונה מרכזית
6. קומפוננטה לתיבת החיפוש (עם הרמקול הקטן בצד שמאל והשלמה אוטומטית איך שמתחילים לחפש)
7. קומפוננטה לשני הכפתורים
8. קומפוננטה לבחירת השפות
9. קומפוננטה לאזור ה Footer
האם זאת החלוקה "הנכונה"? ברור שלא, יש המון חלוקות אפשריות ואין חלוקה אחת נכונה. החלוקה לקומפוננטות עוזרת לנו לחשוב על הבעיה והרבה פעמים במהלך כתיבת האפליקציה אנחנו נשנה את בחירת הקומפוננטות עד שנגיע למשהו שבדיוק מסתדר.
עכשיו בואו נעשה זום-אין על מספר 2 ברשימה שלי, אלה כפתורי הניווט. כפתורי ניווט מאוד דומים אחד לשני מבחינה זאת שיש להם את אותו HTML, אותו עיצוב CSS (לרוב, כי כפתור Sign In כולל צבעים אחרים) ואותו קוד JavaScript. כשיש לנו קומפוננטה שצריכה להופיע מספר פעמים בעמוד בשינויים קטנים אנחנו נשתמש במנגנון Props כדי להתאים את המאפיינים הספציפיים של כל מופע.
מנגנון props אומר שביצירת הקומפוננטה אנחנו יכולים להעביר "פרמטרים" לאותה קומפוננטה, והקומפוננטה תוכל להשתמש בפרמטרים אלה כדי להציג את המידע. במקרה של כפתור ניווט לדוגמה נוכל להעביר לכל "מופע" של הקומפוננטה טקסט אחר וקישור אחר, וכך להשתמש באותה קומפוננטה מספר פעמים ולקבל כל פעם תוצאה שונה - משהו כמו התבנית הבאה:
<template>
<NavLink text="Images" href="https://images.google.com" />
<NavLink text="Gmail" href="https://google.com/mail" />
<NavLink
text="Sign In"
href="https://accounts.google.com/ServiceLogin"
:primary="true"
/>
</template>
בצד של הקומפוננטה אני צריך להגדיר איזה props אני מצפה לקבל (אפשר להגדיר גם מאיזה סוג כל prop צריך להיות), ואז אני יכול להשתמש ב props אלה בתוך התבנית. הנה קוד הקומפוננטה:
<template>
<a href="#" :class="{ 'primary-link': primary }">{{ text }}</a>
</template>
<script>
export default {
props: ["text", "href", "primary"],
name: "NavLink",
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.primary-link {
background: #1a73e8;
color: white;
border-radius: 5px;
}
a {
margin: 5px;
text-decoration: none;
padding: 10px;
}
a:hover {
text-decoration: underline;
}
</style>
## מה זה כל הנקודותיים האלה?
שמתם לב לסימן הנקודותיים לפני המילה class בקוד הקומפוננטה, ולפני המילה primary בקוד התבנית? בטח שאלתם את עצמכם מה המשמעות שלהם ולמה הם מופיעים לפני מאפיינים מסוימים אבל לא מופיעים לפני מאפיינים אחרים. בשביל התשובה שימו לב לערכים שאני מעביר במאפיינים שמקבלים נקודותיים, לעומת הערכים שעוברים דרך מאפיינים ללא נקודותיים:
1. המאפיין text מקבל מידע מסוג String ועובר ללא נקודותיים.
2. המאפיין href מקבל מידע מסוג String ועובר ללא נקודותיים.
3. המאפיין primary מקבל מידע מסוג Boolean ועובר עם נקודותיים.
4. המאפיין class מקבל מידע מסוג אוביקט ועובר עם נקודותיים.
ההתאמה בין סוג הערך לנקודותיים היא לא מקרית. ב Vue, כשרוצים להעביר ערך שאיננו מחרוזת יש להשתמש בנקודותיים כדי לגרום ל Vue לשערך את הביטוי בתור קוד JavaScript ולהעביר את התוצאה שלו.1 421
וכאן אנחנו מגיעים לקסם הראשון של Vue שנקרא ריאקטיביות. למרות שבשום מקום לא כתבתי את זה במפורש, באופן אוטומטי ברגע ש Vue מזהה שערך מסוים באוביקט המידע השתנה אז הוא יחשב מחדש את התבנית ויעדכן את המסך כדי להציג את התוכן המעודכן. זאת הסיבה שהטקסט בפיסקה מתעדכן כל פעם שאני משנה את הטקסט בתיבת הקלט.
## כפתורים ולחיצות
נוסיף לקומפוננטה שלנו כפתור שמאפס את הטקסט כדי לראות גם איך עובדים עם כפתורים. אני מעדכן את הטמפלייט לקוד הבא:
<template>
<input type="text" v-model="text" />
<p>You typed: {{ text }}</p>
<button @click="reset">Reset</button>
</template>
זה מאוד דומה להגדרת כפתור ב HTML רגיל! ההבדל היחיד הוא הסימן המצחיק @click כדי להגדיר מהי הפונקציה שתיקרא בעת לחיצה על הכפתור. בצד הסקריפט אני צריך לכתוב את הפונקציה הרלוונטית בתוך מפתח methods של הדבר שאני מחזיר מהסקריפט, ואותה פונקציה מקבלת את אוביקט המידע בתור פרמטר this שלה. הסקריפט אחרי השינוי נראה כך:
<script>
export default {
name: "HelloWorld",
data() {
return {
text: "Type something...",
};
},
methods: {
reset() {
this.text = "";
},
},
};
</script>
אתם מוזמנים למצוא את התוצאה בקישור https://codesandbox.io/s/brave-varahamihira-u0370?file=/src/components/HelloWorld.vue:134-325 ולנסות ללחוץ על הכפתור כדי לראות איך הוא מוחק את הטקסט. הדבר היפה לקחת מכאן הוא הריאקטיביות - ברגע שהפונקציה מסתיימת והטקסט הופך למחרוזת ריקה, ויו באופן אוטמטי מעדכן גם את העמוד ומוחק את הטקסט מתיבת הקלט ומה p.
## תרגילים
למרות שזה היה רק הפרק הראשון אני חושב שאתם יודעים מספיק על Vue בשביל לעשות נזק. בשלב זה עדיין לא נתקין שום דבר על המחשב וננסה לתרגל דרך האתר https://codesandbox.io/. אחרי יצירת חשבון באתר תוכלו לבחור ליצור פרויקט חדש, לבחור בתבנית את Vue3 ותקבלו פרויקט חדש דומה לזה שהצגתי פה. נסו לקחת את הפרויקט החדש הזה ולעדכן אותו כך שיציג:
1. כפתור ומתחתיו שורת טקסט. בהתחלה בטקסט יהיה כתוב Click The Button ואחרי הלחיצה הטקסט ישתנה ל Ouch!
2. כפתור ומתחתיו שורת טקסט. בהתחלה הטקסט יהיה המספר 0, וכל לחיצה על הכפתור תעלה את הערך ב-1.
3. פיסקת טקסט ששואלת מה שמכם, לידה תיבת קלט ואחריה כפתור. בלחיצה על הכפתור המערכת תיקח את הטקסט מתיבת הקלט ותתיחס אליו בתור שם המשתמש, ואז תשנה את הטקסט בפיסקה למילה Hello ואחריה אותו שם משתמש.
4. תיבת קלט ומתחתיה הצגת אורך הקלט. כלומר אחרי שינוי הערך בתיבת הקלט יתעדכן באופן אוטומטי גם הטקסט להציג את האורך המעודכן של המילה.
5. הציגו 5 תיבות קלט מתואמות, כלומר שינוי טקסט בכל אחת מתיבות הקלט ישנה אוטומטית את הטקסט בכל 4 התיבות האחרות.1 421
font-size: 18px; } </style>את התוצאה של הקוד אפשר לראות לייב בתיבה כאן: <iframe src="https://codesandbox.io/embed/festive-bell-qeij1?fontsize=14&hidenavigation=1&module=%2Fsrc%2Fcomponents%2FHelloWorld.vue&theme=dark" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="festive-bell-qeij1" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" ></iframe> או בקישור: https://codesandbox.io/s/festive-bell-qeij1?file=/src/components/HelloWorld.vue. אם תשחקו עם זה תוכלו לראות שכשאתם משנים את הטקסט בתיבת הטקסט גם הטקסט בפיסקה מתעדכן בהתאמה ושהפיסקה כוללת עיצוב לכתב בגודל 18 פיקסלים. כרגע באפליקציית הדוגמה הקומפוננטה מופיעה פעם אחת, ואינה משותפת בין אפליקציות. אבל הדבר היפה בפיתוח מבוסס קומפוננטות הוא שקל להשתמש באותה קומפוננטה כמה פעמים ביישום. הקובץ App.vue באותו פרויקט הוא שאחראי על יצירת הקומפוננטה. התוכן שלו כרגע הוא:
<template>
<HelloWorld />
</template>
<script>
import HelloWorldVue from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld: HelloWorldVue,
},
};
</script>
<style>
</style>
וזה מדהים כי גם קובץ זה הוא קומפוננטה. נסו אתם בכניסה לקישור או בתיבה כאן בפוסט לשנות את הקובץ ולהוסיף עוד כמה עותקים של הקומפוננטה - כלומר בתוך ה template לכתוב מספר פעמים את האלמנט HelloWorld:
<template>
<HelloWorld />
<HelloWorld />
<HelloWorld />
<HelloWorld />
</template>
תוך רגע יופיעו עוד תיבות טקסט ועוד פיסקאות, וכל תיבה תהיה מתואמת עם הפיסקה שלה.
## מה עוד היה בקומפוננטה
נחזור לקומפוננטה שכתבנו וננסה להבין מה היה שם? איך זה עבד? נחזור לקומפוננטה שכתבנו ונתבונן שוב בקטע ה script שלה:
export default {
name: "HelloWorld",
data() {
return {
text: "Type something...",
};
},
};
דבר ראשון שיראה מוזר פה לחלק מכם הוא התחלת הסקריפט בביטוי export default. זהו כתיב המודולים של ES6 וחשוב להכיר אותו (ובאופן כללי את הרעיונות המרכזיים של ES6 והתקנים החדשים יותר) לפני שאפשר להשתמש בפריימוורקים כמו Vue, React ו Angular. בגדול כתיב זה אומר שהאוביקט שאנחנו כותבים עכשיו יהיה הדבר המרכזי מתוך הסקריפט, והוא בעצם יהיה הדבר שקבצים אחרים "יקבלו" כשהם יטענו את הסקריפט שלי.
האוביקט הזה מורכב משני שדות: השדה name שקובע את שם הקומפוננטה, והשדה data שמכיל את המידע שהקומפוננטה מכירה. אגב, שדה name רלוונטי רק להדפסות ו Debugging והקומפוננטה תעבוד ממש בסדר גם בלעדיו. השדה המעניין הוא data.
שימו לב למבנה של data - מדובר בפונקציה שמחזירה אוביקט. זה אומר שכל פעם ש Vue צריך ליצור "עוד" קומפוננטה מאותו סוג הוא יוכל להפעיל מחדש את data ולקבל את כל המידע של הקומפוננטה מחדש. המידע הזה משמש בשילוב עם התבנית כדי להציג דברים על המסך. במקרה שלנו המידע מורכב משדה בודד בשם text, ובואו נראה איך אני משתמש בו בתבנית:
<template>
<input type="text" v-model="text" />
<p>You typed: {{ text }}</p>
</template>
אפשר לראות שאני משתמש במידע בשני מקומות בתבנית:
1. בתוך תוכן אלמנט p אני משתמש בכתיב {{ text }}. כתיב זה אומר ל Vue שאני רוצה לשתול את הערך של שדה המידע text במקום הביטוי עם הסוגריים המסולסלים.
2. בתור הערך של ה Attribute שנקרא v-model אני משתמש במילה text. המאפיין v-model הוא מאפיין מיוחד, ואנחנו מזהים את זה גם כי אנחנו לא מכירים אותו מ HTML וגם בגלל התחילית v-. מאפיין מיוחד כזה נקרא Directive, והמאפיין הספציפי v-model הוא Directive די מתוחכם. הוא יוצר בצורה אוטומטית קוד טיפול באירוע input ומחבר אותו לשדה text, כך שכל פעם שהטקסט בתיבה משתנה אוטומטית גם ערך השדה text באוביקט המידע מתעדכן.1 421
# מדריך Vue למתחילים - פרק 1 - קומפוננטה ראשונה ב Vue
ויו היא פריימוורק לפיתוח יישומי Front End מבוססי קומפוננטות. פיתוח מבוסס קומפוננטות הוא הפרדיגמה המרכזית היום בעולם פיתוח ה Front End ויש לה כמובן יתרונות וחסרונות בהשוואה לשיטות עבודה שהיו נהוגות בעבר. ויו עצמה מיצבה את עצמה בתור ספריית פיתוח הקומפוננטות הפשוטה והידידותית ביותר מהמשפחה וכך זכתה לפופולריות גדולה בקרב מפתחים.
במדריך זה אראה לכם איך לכתוב קוד צד לקוח מבוסס קומפוננטות באמצעות Vue החל מהצעד הראשון. פרק זה הוא החלק הראשון במדריך ואני מתכנן להמשיך לפרסם חלקים נוספים פה בבלוג בתקופה הקרובה אבל זה כנראה לא יהיה כל יום, אז שווה לעקוב (או שאפשר לחזור לפוסט הזה בעוד חודש ואז כבר הכל יהיה כתוב ויהיה לנו אינדקס מסודר).
## מהו תכנות מבוסס קומפוננטות ולמה זה כדאי
דפי אינטרנט באופן רגיל מורכבים משלוש טכנולוגיות משלימות: HTML, CSS ו JavaScript, וכל טכנולוגיה אחראית על היבט אחר בפונקציונאליות של העמוד. ב HTML אנחנו כותבים את תוכן הדף, ב CSS מעצבים את התוכן הזה וב JavaScript מקודדים את האינטרקציות של הדף עם המשתמש.
מבנה זה מכריח אותנו (או לפחות מאוד מעודד אותנו) להסתכל על העמוד כמכלול - בכתיבת ה CSS להשתמש במה שאנחנו יודעים על ה HTML; בכתיבת ה JavaScript להשתמש במה שאנחנו יודעים על ה HTML וה CSS וכך הלאה. באתרים קטנים זה מאוד נוח כי אפשר להשאיר בראש את מה שקורה בכל מקום באתר ולראות את הקוד כתמונה אחת מרכזית.
ברגע שהאתר גדל העסק מסתבך. באתרים גדולים קוד JavaScript של חלק אחד באתר עלול להפריע לקוד JavaScript של חלק אחר. קוד CSS של רכיב מסוים באתר כתוב בערבוביה עם קוד CSS של כל החלקים האחרים, ואז אם למשל מחקתי מה HTML את גלריית התמונות לא בטוח שאני אזכור למחוק את כללי העיצוב המתאימים לה מה CSS (והרבה פעמים אני פוחד למחוק משם, כי אולי הכללים משפיעים על חלקים אחרים בעמוד).
כשהדפים גדולים אנחנו גם מתחילים לחלום על שיתוף קוד בין דפים שונים, וגם זה דבר שמאוד קשה לעשות כשכל הקוד הוא גלובאלי ומניח המון דברים על מבנה העמוד.
ככל שקוד צד-לקוח הפך גדול ומסובך יותר כך מפתחים וארכיטקטים החלו לחשוב על רעיונות איך להפוך את ההתמודדות עם הקוד לקלה יותר באמצעות הפיכתו למודולרי. אחד הרעיונות הראשונים בתחום זה נקרא MVC והוא דיבר על זה שחלק מהקוד יהיה אחראי על התצוגה וחלק אחר יהיה אחראי על הלוגיקה. אבל MVC ברוב המקרים רק הפך את הקוד ליותר מסובך ולא הצליח להתמודד עם האופי המודולארי של פיתוח ממשק משתמש וספציפית של השילוב בין שלוש הטכנולוגיות השונות. רוב ה MVC Frameworks התמקדו רק ב JavaScript וניסו לבטל לחלוטין את ה HTML וה CSS.
מאז הפרדיגמה השתכללה. הפריימוורק הראשון והמרכזי שהגיע עם רעיון חדש נקרא React ופריימוורקס נוספים לא איחרו להדביק את הפער, והרעיון החדש הזה נקרא תכנות מבוסס קומפוננטות.
קומפוננטה היא חלק בעמוד שמכיל גם את ה HTML, גם את ה CSS וגם את ה JavaScript ואפשר להעביר אותו בין פרויקטים או בין דפים. אפשר לחשוב על גלריית תמונות בדף בתור קומפוננטה, תפריט עליון יכול להיות קומפוננטה, תפריט צד יהיה קומפוננטה אחרת ותיבת חיפוש קומפוננטה נוספת. לקומפוננטה יש קשר לקומפוננטות אחרות, למשל קומפוננטה של גלריית תמונות יכולה להיות מורכבת מקומפוננטה כללית יותר של "קרוסלה", אבל הדבר המרכזי לקחת פה הוא שקומפוננטה היא עצמאית: יש לה ממשק מוגדר עם העולם שסביבה, יש לה את התוכן שלה, את הקוד שלה, את העיצוב שלה ואפילו את הבדיקות שלה, ולכן קוד שמורכב מקומפוננטות הוא קוד קל יותר לתחזוקה.
מתכנתי Front End שרגילים לחשוב על HTML/CSS/JavaScript וצריכים לעבור לחשוב על קומפוננטות יצטרכו לשנות גישה. במקום להסתכל על כל העמוד ולחשוב איזה HTML לכתוב עבורו, אנחנו נתחיל בסקירה ממבט על של העמוד, נזהה איזה קומפוננטות מופיעות בו ונתחיל לבנות את הקומפוננטות האלה אחת אחרי השניה. בסוף נרכיב את כל הקומפוננטות יחד כדי לקבל את העמוד המלא.
## איך נראית קומפוננטה ב Vue
תכף נגיע לכתוב אפליקציית Vue מלאה אבל בואו נתחיל קודם מהעניין המרכזי - הוא הקומפוננטה. קומפוננטה ב Vue נשמרת בקובץ עם סיומת vue ומורכבת משלושה חלקים, שהם שלושת טכנולוגיות הווב שאנחנו מכירים: התבנית (HTML), העיצוב (CSS) והקוד (JavaScript). הנה קומפוננטה ראשונה שמכילה את שלושת החלקים:
<template>
<input type="text" v-model="text" />
<p>You typed: {{ text }}</p>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
text: "Type something...",
};
},
};
</script>
<style scoped>
p {
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
