רכיבים מותאמים אישית מאפשרים לכם ליצור תגי HTML משלכם. רשימת המשימות הזו כוללת שיטות מומלצות שיעזרו לכם ליצור רכיבים באיכות גבוהה.
רכיבים מותאמים אישית מאפשרים לכם להרחיב HTML ולהגדיר תגים משלכם. אלה
היא תכונה חזקה מאוד, אבל היא גם ברמה נמוכה,
ברור תמיד מהי הדרך הטובה ביותר ליישם את הרכיב שלך.
כדי לעזור לך ליצור את החוויה הטובה ביותר, ריכזנו כאן
ברשימת המשימות. הוא מפרט את כל הדברים שלדעתנו צריכים כדי
רכיב מותאם אישית עם התנהגות טובה.
רשימת המשימות
DOM של הצללה
כדי להקיף סגנונות, צריך ליצור שורש של הצללה.
למה?
הכללת סגנונות ברמה הבסיסית (root) של ההצללה של הרכיב מבטיחה שהסגנונות יפעלו
בלי קשר למקום שבו משתמשים בו. זה חשוב במיוחד אם מפתחים
רוצה למקם את הרכיב בתוך שורש הצללה של רכיב אחר. הזה
הוא רלוונטי גם לרכיבים פשוטים, כמו תיבת סימון או לחצן בחירה. יכול להיות
מקרה שבו התוכן היחיד בתוך שורש הצללית יהיה הסגנונות
בעצמם.
ה-constructor הוא במקרים שבהם יש לכם ידע בלעדי על הרכיב שלכם.
זה זמן מצוין להגדיר את פרטי ההטמעה שאתם לא רוצים לדעת
של רכיבים שמתעסקים איתם כל הזמן. הפעולה הזאת בוצעה בקריאה חוזרת (callback) מאוחרת יותר, למשל
connectedCallback, כלומר צריך להגן מפני
במצבים שבהם נותק האלמנט שלך ואז צורף מחדש למסמך.
שימוש ב<משבצת> כדי להקרין צאצאים של DOM אור ב-DOM של הצללים
למה?
מתן הרשאה למשתמשים ברכיב לציין תוכן ברכיב כצאצאי HTML, הופך את הרכיב לקומפוזבילי יותר. כשהדפדפן לא תומך ברכיבים מותאמים אישית, התוכן בתוך התוכן נשאר זמין, גלוי ונגיש.
הגדרת סגנון תצוגה :host (למשל, block,
inline-block, flex), אלא אם בחרת בברירת המחדל של
inline
למה?
הרכיבים המותאמים אישית הם display: inline כברירת מחדל, לכן מגדירים אותם
ל-width או ל-height לא תהיה השפעה. לעיתים קרובות
באופן מפתיע למפתחים, ועלול לגרום לבעיות שקשורות לנושאים הבאים:
פריסת הדף. אלא אם אין לך העדפה למסך inline,
צריך להגדיר תמיד ערך ברירת מחדל ל-display.
מוסיפים סגנון תצוגה :host שמכבד את המאפיין המוסתר.
למה?
רכיב מותאם אישית עם סגנון ברירת המחדל של display, לדוגמה
:host { display: block }, תבטל את רמת הפירוט הנמוכה יותר
מובנה
מאפיין hidden.
זה עלול להפתיע אותך אם צפויה הגדרה של hidden
ברכיב שלך כדי לעבד אותו display: none. כמו כן
לסגנון ברירת המחדל של display, הוספת תמיכה ב-hidden
עם :host([hidden]) { display: none }.
מאפיינים גלובליים הם המאפיינים שקיימים בכל רכיבי ה-HTML. במידה מסוימת
לדוגמה: tabindex ו-role. רכיב מותאם אישית
אולי כדאי להגדיר את הערך הראשוני של tabindex ל-0 כך שהמקלדת
שניתן להתמקד בו. אבל תמיד צריך לבדוק קודם אם המפתח שמשתמש ב-
הרכיב שלך הגדיר זאת עם ערך אחר. לדוגמה, אם הם הגדירו
tabindex עד 1, זה סימן לכך שהוא לא רוצה
להיות אינטראקטיבי.
נתונים פרימיטיביים (מחרוזות, מספרים, בוליאניים) צריכים תמיד להיות מופעלים על ידי כל אחד מהמאפיינים
או מאפיינים.
למה?
רכיבים מותאמים אישית, כמו הרכיבים המובְנים שלהם, צריכים להיות ניתנים להגדרה.
אפשר להעביר את ההגדרות באופן הצהרתי, באמצעות מאפיינים או באופן חיוני
באמצעות מאפייני JavaScript. באופן אידיאלי כדאי לקשר כל מאפיין גם אל
נכס תואם.
רצוי לשמור על סינכרון בין מאפיינים ומאפיינים של נתונים פרימיטיביים, המשקפים
לשיוך, ולהפך.
למה?
אף פעם אי אפשר לדעת איך משתמש יקיים אינטראקציה עם הרכיב שלכם. ייתכן שהם
מגדירים מאפיין ב-JavaScript, ואז מצפה לקרוא את הערך הזה
באמצעות API כמו getAttribute(). אם לכל מאפיין יש
לנכס המתאים ושניהם משתקפים, זה יקל
למשתמשים לעבוד עם הרכיב שלך. במילים אחרות, להתקשר
setAttribute('foo', value) צריך גם להגדיר ערך תואם
foo ולהפך. כמובן שיש יוצאים מן הכלל
כלל זה. לא מומלץ לשקף מאפיינים של תדירות גבוהה, למשל
currentTime בנגן וידאו. חשוב להפעיל שיקול דעת. אם
נראה שמשתמש יוצר אינטראקציה עם נכס או מאפיין,
אינה מעמסה כדי לשקף זאת.
המטרה היא לקבל רק נתונים עשירים (אובייקטים, מערכים) כמאפיינים.
למה?
באופן כללי, אין דוגמאות לרכיבי HTML מובנים
מקבלים נתונים עשירים (אובייקטים ומערכים של JavaScript פשוט) באמצעות
. נתונים עשירים מתקבלים במקום זאת באמצעות קריאות ל-method או
נכסים. יש כמה חסרונות ברורים של קבלת נתונים עשירים,
המאפיין הזה עשוי להיות יקר כדי ליצור סריאליזציה של אובייקט גדול למחרוזת,
הפניות לאובייקטים יאבדו בתהליך המחרוזת הזה. עבור
לדוגמה, אם מבצעים מחרוזת של אובייקט שיש לו הפניה לאובייקט אחר,
או צומת DOM, ההפניות האלה יאבדו.
הם לא משקפים מאפיינים של נתונים עשירים במאפיינים.
למה?
ההוספה של מאפיינים של נתונים עשירים למאפיינים היא יקרה באופן מיותר,
דרישה לבצע סריאליזציה (סריאליזציה) לאותם אובייקטי JavaScript. אלא אם
יש תרחיש לדוגמה שאפשר לפתור רק באמצעות התכונה הזו,
להימנע ממנה.
כדאי לבדוק אם יש מאפיינים שהוגדרו לפני הרכיב
שודרג.
למה?
מפתח שמשתמש ברכיב שלך יכול לנסות להגדיר מאפיין על האלמנט
לפני שהגדרתו נטענה. במיוחד אם
משתמשים ב-framework שמטפל ברכיבים של טעינה וחותמים אותם.
לדף, ולקשר את המאפיינים שלהם למודל.
רכיבים שצריכים לבטא את המצב שלהם צריכים לעשות זאת באמצעות מאפיינים.
באופן כללי, המאפיין class נחשב לבעלים של
שמשתמשים באלמנט שלך, וכתיבת תוכן אפשרית בעצמך עלולה להיות למשתמש בלתי מכוון
להיכנס למחלקות של מפתחים.
אירועים
אירועי שליחה בתגובה לפעילות של רכיבים פנימיים.
למה?
ברכיב שלכם עשויים להיות מאפיינים שמשתנים בתגובה לפעילות
רק הרכיב שלך יודע על הקיום. לדוגמה, אם טיימר או אנימציה
או שהטעינה של המשאב מסיימת. כדאי לשלוח אירועים
בתגובה לשינויים האלה, כדי להודיע למארח שמצב הרכיב
אחרת.
לא לשלוח אירועים בתגובה להגדרת נכס על ידי המארח (למטה
).
למה?
שליחת אירוע בתגובה להגדרת נכס בפני מארח היא מיותרת
(המארח יודע את המצב הנוכחי כי הוא רק הגדיר אותו). שליחת אירועים
בתגובה להגדרת מארח, מאפיין עלול לגרום ללולאות אינסופיות עם נתונים
מערכות קישור.
ייתכן שמפתח שמשתמש ברכיב שלך ירצה לבטל חלק
את המצב הראשוני שלו. לדוגמה, שינוי ה-role של ARIA או של יכולת המיקוד באמצעות
tabindex. בודקים אם המאפיינים האלה ומאפיינים גלובליים אחרים הוגדרו
לפני שתחילו את הערכים שלכם.
יכול להיות שמפתח ינסה להגדיר מאפיין ברכיב שלכם לפני
נטענה. במיוחד נכון אם המפתח משתמש
המטפלת ברכיבים בטעינה, מכניסה אותם לדף
שמקשרות את המאפיינים שלהן למודל.
בדוגמה הבאה, חברת Angular מקשרת באופן הצהרתי את המודל של המודל
מאפיין isChecked למאפיין checked של תיבת הסימון. אם ההגדרה של
הוראות הסימון
המאפיין המסומן לפני שהרכיב שודרג.
רכיב מותאם אישית צריך לטפל בתרחיש הזה על ידי בדיקה אם יש לו מאפיינים
כבר הוגדר במופע שלו. <howto-checkbox>
מדגימה את הדפוס הזה באמצעות שיטה שנקראת _upgradeProperty().
_upgradeProperty() מתעד את הערך מהמכונה שלא משודרגת ומוחק אותה
את המאפיין כך שלא יוטיל הצללה על מגדיר המאפיין של הרכיב המותאם אישית.
כך, כשהגדרת הרכיב נטענה בסופו של דבר, היא תוכל מייד
לשקף את המצב הנכון.
מניעת בעיות של הרשמה מחדש
מפתה להשתמש בattributeChangedCallback() כדי לשקף את המצב
לנכס הבסיסי, לדוגמה:
// When the [checked] attribute changes, set the checked property to match.attributeChangedCallback(name,oldValue,newValue){if(name==='checked')this.checked=newValue;}
אבל הפעולה הזו יכולה ליצור לולאה אינסופית אם המרכיב של המאפיין ישקף גם את
את המאפיין.
setchecked(value){constisChecked=Boolean(value);if(isChecked)// OOPS! This will cause an infinite loop because it triggers the// attributeChangedCallback() which then sets this property again.this.setAttribute('checked','');elsethis.removeAttribute('checked');}
אפשרות אחרת היא לאפשר לרכיב המגדיר של הנכסים לשקף את המאפיין.
שהמקבל יקבע את הערך שלו על סמך המאפיין.
בדוגמה הזו, הוספה או הסרה של המאפיין תגדיר גם את הנכס.
לבסוף, אפשר להשתמש בattributeChangedCallback() לטיפול בתופעות הלוואי
כמו החלת מצבי ARIA.
attributeChangedCallback(name,oldValue,newValue){consthasValue=newValue!==null;switch(name){case'checked':// Note the attributeChangedCallback is only handling the *side effects*// of setting the attribute.this.setAttribute('aria-checked',hasValue);break;...}}
[[["התוכן קל להבנה","easyToUnderstand","thumb-up"],["התוכן עזר לי לפתור בעיה","solvedMyProblem","thumb-up"],["סיבה אחרת","otherUp","thumb-up"]],[["חסרים לי מידע או פרטים","missingTheInformationINeed","thumb-down"],["התוכן מורכב מדי או עם יותר מדי שלבים","tooComplicatedTooManySteps","thumb-down"],["התוכן לא עדכני","outOfDate","thumb-down"],["בעיה בתרגום","translationIssue","thumb-down"],["בעיה בדוגמאות/בקוד","samplesCodeIssue","thumb-down"],["סיבה אחרת","otherDown","thumb-down"]],["עדכון אחרון: 2017-08-14 (שעון UTC)."],[],[]]