אינטרנט ישראל
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
ראשי » פיתוח אינטרנט » פיתוח ב-JavaScript » יצירה מחדש של blink באמצעות native web component

יצירה מחדש של blink באמצעות native web component

רן בר-זיק פברואר 11, 2018 7:07 am 12 תגובות

יצירת קומפוננטות באמצעות ג'אווהסקריפט בלבד

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.

המאמר הזה מבוסס על ההרצאה שהעברתי במיטאפ האחרון בסדרת Tech Talk Teach שהתקיימה במשרדי OATH ישראל (שם אני עובד). במיטאפ הוקדש לשחזור טכנולוגיות משנות התשעים באמצעות טכנולוגיה חדשה. ההרצאה היתה היתולית בתוכנה (אף אחד באמת לא רוצה את blink) אבל הטכנולוגיה היא אכן אמיתית ולפי דעתי היא הכיוון שאליו התחום הולך. הטכנולוגיה כרגע נתמכת במלואה עם כרום בלבד ובעתיד גם בפיירפוקס. כרגע ניתן להשתמש בפוליפילים כדי לאפשר תמיכה.

המצגת:

מי מכיר את תגית <blink>? זו תגית שהיתה פופולרית בשנות ה-90 והיה לה שימוש מדהים במיוחד – כל מה שהיא עטפה הבהב! ממש כך!

אבל למרבה הצער, ארגון ה-W3C הבינלאומי החליט להרוג את התגית הזו! למה? ובכן, הם טענו שהתגית הזו בעייתית כי היא לא נגישה: לקויי ראייה ועם בעיות אפילפסיה יתקשו להתמודד איתה. התגית הזו מערבבת בין תצוגה לשימושיות כיוון שכל ענייני התצוגה והאנימציה צריכים להיות ב-CSS. וכך התגית הזו נזרקה לפח האשפה של ההיסטוריה. כמה מצער, כיוון שהתגית הזו התנוססה בשעתו על גבי מאות אלפי אתרי בית של אנשים בגיאוסיטיז, שירות אחסון האתרים מתקופות אנו-באנו.

אבל אנחנו יכולים ליצור אותה! איך? עם web component. היכולת של ג'אווהסקריפט ליצור קומפוננטות ללא כל ספרייה או פריימוורק. במקום להשתמש באנגולר, ריאקט, ויו או כל פריימוורק אחר שנוצר על ידי מפתחי ג'אווהסקריפט מזוקנים והיפסטרים. באמצעות הטכנולוגיה הזו אנחנו יכולים לייצר קומפוננטות עצמאיות שלא תלויות בסביבה שלהן ולא מושפעות ממנה. וזה כל כך פשוט! באמת!

הצעד הראשון הוא הכרזה על web component באמצעות window.customElements.define שמקבלת שני ארגומנטים: הראשון הוא שם הקומפוננטה כפי שנכניס אותו ב-HTML (תמיד מופרד במקף ולא יכול להיות בלי מקף). והשני הוא השם של הקלאס הג'אווהסקריפטי.


window.customElements.define('blink-reborn', blink);

איך הקלאס נראה? פשוט שבפשוטים! ראשית הוא יורש מ-HTMLElement (קבלו את זה כעובדה, כך האימפלמנטציה דורשת) ובקונסטרקטור שלו יש לנו את super. המתודה השניה היא connectedCallback שרצה מייד לאחר שהקומפוננטה מתרנדרת ובה אנחנו יכולים לעשות מה שאנחנו רוצים. כאן יש לי הפעלה של ה-shadow dom.


class blink extends HTMLElement {
  constructor() {
    super();
  }
  
  connectedCallback() { // Running in the begenning
    this.insideText = this.innerHTML;
    this.shadow = this.attachShadow({mode: 'open'});
    this.shadow.innerHTML = this.insideText;
  }
}

window.customElements.define('blink-reborn', blink);

כדי לקרוא לקומפוננטה, כל מה שאני צריך לעשות זה את זה:


<blink-reborn>BLINK IS NOT DEAD!</blink-reborn>

ShadowDOM

זה שם מאוד מאיים למשהו מאוד פשוט. אני רוצה שה-DOM של הקומפוננטה יהיה נפרד מה-DOM של שאר המסמך. אם יש CSS שמשפיע על שאר ה-HTML, אני לא רוצה שהוא ישפיע על הקומפוננטה שלי. אם יש CSS בתוך הקומפוננטה שלי, אני לא רוצה שהוא יזלוג החוצה. shadow DOM פשוט מאפשר לי לשמור על הפרדה מלאה בין ה-HTML של הקומפוננטה לבין כל מה שקורה שבחוץ. כיף כיף כיף :). איך אני יוצא shadow DOM בקומפוננטה שלי? פשוט!

ראשית, לוקח את כל הטקסט ש-<blink-reborn> מקיף ומכניס אותו לתוך this.insideText כי אני רוצה להשתמש בו יותר מאוחר. איך? ככה:

    this.insideText = this.innerHTML;

עכשיו אני יוצר את ה-shadow DOM ומכניס אותו לתוך משתנה שנקרא this.shadow. זה חשוב כי הוא הולך להחליף את כל ה-documnet שאני הולך לקרוא לו בקומפוננטה שלי. אני רוצה להכניס טקסט כלשהו לקומפוננטה? אני חייב להשתמש ב-this.shadow.innerText או innerHTML. אני רוצה לבחור אלמנט מתוך הקומפוננטה? this.shadow.querySelector. יש לו את כל המתודות ואת כל התכונות של document, אבל הוא פנימי ופרטי רק לי.

    this.shadow = this.attachShadow({mode: 'open'});

בשורה השלישית אני פשוט מכניס את ה-insideText שיצרתי בשורה הראשונה ל-shadowDOM. זה מה שמאפשר לי לשמור את מה שהמשתמש הכניס בין התגיות של הקומפוננטה שלי.

    this.shadow.innerHTML = this.insideText;

אם תפתחו inspect ותסתכלו על הרכיב, תוכלו לראות שבמקום document יש לי shadow root:

אינספקטור ל-shadow root
אינספקטור ל-shadow root

הנה דוגמה חיה!

See the Pen marquee and blink phase 1 by Ran Bar-Zik (@barzik) on CodePen.

אבל רגע! זו לא ממש דוגמה טובה במיוחד, לא? איפה ההבהוב? איפה הכפיים?

על מנת להתקדם, אני רוצה לעטוף את מה שהמשתמש מספק לי – כלומר הטקסט (או האלמנטים שבין התגיות של blink-reborn באלמנט אחר כדי שאוכל לעצב את זה. איך אני עושה את זה? זה ג'אווהסקריפט!זה לא פריימוורק. כל מה שאנחנו יודעים מג'אווהסקריפט רגיל יעבוד גם פה. אז מה שאני אעשה זה:


class blink extends HTMLElement {
  constructor() {
    super();
  }
  
  connectedCallback() { // Running in the begenning
    this.insideText = this.innerHTML;
    this.shadow = this.attachShadow({mode: 'open'});
    this.shadow.innerHTML = `

${this.insideText}

`; } } window.customElements.define('blink-reborn', blink);

במקום להכניס ל-shadow.innerHTML את הטקסט שהמשתמש הכניס, אני אעטוף אותו ב-p עם id. אם הסינטקס של הטמפלייט לא מוכר לכם (זה עם הגרש העקום), זה הזמן לעבור על הפיצ'ר הממש פשוט הזה ב-ES6.

איך זה נראה, לא שונה במיוחד, אבל אם אני אעשה inspect, אני אראה שאת התוכן בתוך ה-shadow DOM עוטף p קטן וחמוד.

See the Pen marquee and blink phase 2 by Ran Bar-Zik (@barzik) on CodePen.

אלמנט p שעוטף את התוכן שלו
אלמנט p שעוטף את התוכן שלו

טוב, עדיין לא מה שאנחנו רוצים. מה עם קצת CSS? טוב, גם זה די קל. כאמור יש לי כאן ג'אווהסקריפט פשוט שבפשוטים. כל מה שאני צריך לעשות זה ליצור CSS ולהכניס אותו. אני אשתמש ביצירת ה-CSS באופן מאוד נאיבי. אבל זה די ברור.


class blink extends HTMLElement {
  constructor() {
    super();
  }
  
  connectedCallback() { // Running in the begenning
    this.insideText = this.innerHTML;
    this.shadow = this.attachShadow({mode: 'open'});
    this.shadow.innerHTML = `

${this.insideText}

`; this.addStyle(); } addStyle() { const style = document.createElement('style'); style.textContent = ` p { color: red; } `; this.shadow.appendChild(style); } } window.customElements.define('blink-reborn', blink);

פונקצית addStyle פשוט יוצרת CSS ומוסיפה אותו. ההבדל היחידי בין זה לבין ג'אווהסקריפט רגיל הוא שאני עושה appendChild ל- shadow dom. זה הכל. ברגע שאני משתמש ב-shadow, אני פשוט פונה אליו במקום ל-document. זה הכל. ככה זה נראה:

See the Pen marquee and blink phase 3 by Ran Bar-Zik (@barzik) on CodePen.

טוב, אנחנו לא רוצים טקסט אדום, אנחנו רוצים אנימציה! כאן אני פשוט אחליף את ה-CSS שצובע את ה-p באדום, ל-CSS שעושה אנימציות. פשוט ביותר. כאמור, אנחנו בג'אווהסקריפט הכי פשוט שיש. לא פריימוורק, לא בלגן. CSS, ג'אווהסקריפט. c'est tout.


class blink extends HTMLElement {
  constructor() {
    super();
  }
  
  connectedCallback() { // Running in the begenning
    this.insideText = this.innerHTML;
    this.shadow = this.attachShadow({mode: 'open'});
    this.shadow.innerHTML = `

${this.insideText}

`; this.addStyle(); } addStyle() { const style = document.createElement('style'); style.textContent = ` #blink { animation: blink-animation 1s steps(5, start) infinite;} @keyframes blink-animation { to { visibility: hidden; } `; this.shadow.appendChild(style); } } window.customElements.define('blink-reborn', blink);

וככה זה נראה! איזו חגיגה! סוף סוף יצרנו את התגית blink ונוכל להשתמש בה באתר שלנו בגיאוסיטיז!

See the Pen marquee and blink phase 4 by Ran Bar-Zik (@barzik) on CodePen.

אבל רגע, למה שלא נשפר? נניח ואני רוצה לקבוע את קצב ההבהוב על ידי תכונה שמועברת באלמנט ב-HTML. משהו בסגנון הזה:


<blink-reborn bit="1">BLINK IS NOT DEAD!</blink-reborn>

ה-bit מעביר לי את קצב האנימציה. הדבר היחידי שאני צריך לעשות במקרה הזה, זה להגדיר get לתכונת ה-bit ואת זה אני עושה ב-class שלי. זה כל כך פשוט שזה מגוחך. עושים את זה כך:


class blink extends HTMLElement {
  constructor() {
    super();
  }
  
  connectedCallback() { // Running in the begenning
    this.insideText = this.innerHTML;
    this.shadow = this.attachShadow({mode: 'open'});
    this.shadow.innerHTML = `

${this.insideText}

`; this.addStyle(); } get bit() { const bit = this.getAttribute('bit'); return bit; } addStyle() { const style = document.createElement('style'); style.textContent = ` #blink { animation: blink-animation ${this.bit}s steps(5, start) infinite;} @keyframes blink-animation { to { visibility: hidden; } `; this.shadow.appendChild(style); } } window.customElements.define('blink-reborn', blink);

באמצעות getAttribute שמקבלת ארגומנט של שם הערך ומוצבת בפונקצית get, אני יכול לקבוע שכל מה שמשתמש מכניס ל-bit ב-HTML, יהיה לי זמין ב-this.bit וכמובן להשתמש בו ב-CSS. עכשיו יש לי תגית משופרת! ואני יכול לקבוע את קצב ההבהוב! שימו לב לחגיגה הבאה:

See the Pen all together now! by Ran Bar-Zik (@barzik) on CodePen.

אכן, אושר גדול! שימו לב שהשתמשתי פה בתגיות נוספות שה-W3C מאיים עליהן בכליה: center ו-marquee. אבל אל דאגה, ברגע שהן ייתמו מן העולם, נוכל להמשיך את החגיגה וליצור אותן מחדש באמצעות web component שנותנת לנו כלים חדשים לעשות דברים ישנים בדרך טובה הרבה יותר 🙂

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.
JavaScript Web Components

12 תגובות

  1. שחר הגב פברואר 11, 2018 בשעה 9:44 am

    אחלה מדריך
    תודה

  2. שי הגב פברואר 11, 2018 בשעה 11:20 am

    אתה יכול בבקשה לתת דוגמה ליישום ריאלי?

    • רן בר-זיק הגב פברואר 11, 2018 בשעה 6:26 pm

      תכנון מבוסס קומפוננטות נפוץ בהרבה מקומות (כמו במקום שבו אני עובד) ונשען על הקונספטים שיש באנגולר 1.6 ומעלה, ריאקט ו-ויאו. במסגרת של בנייה מבוססת קומפוננטות, כל רכיב הוא קומפוננטה העומדת בפני עצמה. אתה יכול להביט ב-angular material כדי לראות איך דבר כזה נראה למשל.

  3. גלעד הגב פברואר 11, 2018 בשעה 11:40 am

    אכן חזרה לשנות ה90

  4. עמית הגב פברואר 11, 2018 בשעה 11:43 am

    לא שאני חלילה מתנגד לקצת JS, אבל לא היה קל יותר לסגור את זה ב-CSS פשוט?

    https://jsfiddle.net/txudjrw5/1/

    • רן בר-זיק הגב פברואר 11, 2018 בשעה 12:01 pm

      ברור שאפשר – כי בסופו של דבר הפתרון עצמו נשען על CSS. אבל אם אני רוצה לשנות את הקצב של ההבהוב באופן פשוט – כמו שהראיתי לקראת החלק האחרון של המאמר, זה יהיה הרבה יותר קשה למימוש ב-CSS.
      חוץ מזה, וזה יותר חשוב: מדובר בסופו של דבר בהדגמה (ועוד היתולית! מי לעזאזל ירצה את ה-blink??) שנועדה להראות כמה זה קל לעבוד עם native web component 🙂

  5. ינאי הגב פברואר 11, 2018 בשעה 7:40 pm

    אז הסינטקס הישן כמו:
    var tmpl = document.querySelector('template');
    var host = document.querySelector('.img-slider');
    var root = host.createShadowRoot();
    root.appendChild(document.importNode(tmpl.content, true));

    כבר לא יעבוד?

    • רן בר-זיק הגב פברואר 11, 2018 בשעה 8:21 pm

      למה לא יעבוד? בטח שיעבוד! זה ג'אווהסקריפט נייטיב. כל מה שעובד לך בסקריפט רגיל יעבוד לך גם פה 🙂 מבטיח. למה שלא תנסה? תערוך את ה-codepen ותראה.

  6. ינאי הגב פברואר 11, 2018 בשעה 7:45 pm

    עוד שאלה – כבר לא משתמשים בתגית template ? עבור קומפוננטות?

    • רן בר-זיק הגב פברואר 11, 2018 בשעה 8:22 pm

      אין שום בעיה להשתמש בשום דבר בקומפוננטה. זה מה שיפה בכל הסיפור הזה.

  7. ינאי הגב פברואר 11, 2018 בשעה 8:44 pm

    מצאתי את זה:

    https://hayato.io/2016/shadowdomv1/

  8. מוטי הגב פברואר 12, 2018 בשעה 5:07 am

    נתקלתי בזה https://stenciljs.com
    נראה מעניין

השארת תגובה

ביטול

ללמוד ג'אווהסקריפט בעברית

ללמוד לתכנת ג'אווהסקריפט בעברית שגייס יותר משלוש מאות אלף שקל ולמעלה מ-2000 תומכים - בואו ללמוד עכשיו איך לתכנת.

רשימת הנושאים
  • מדריכים
    • ריאקט
    • טייפסקריפט
    • ECMAScript 6
    • ES20XX
    • Node.js
    • Express
    • רספברי פיי
    • Babel
    • docker
    • MongoDB
    • Git
    • לימוד MySQL
    • SASS
    • jQuery
    • CSS3
    • HTML 5
    • SVN
    • LESS
  • פיתוח אינטרנט
    • פתרונות ומאמרים על פיתוח אינטרנט
    • jQuery Scripts
    • jQuery למתקדמים
    • יסודות בתכנות
    • נגישות אינטרנט
  • חדשות אינטרנט
  • מידע כללי על אינטרנט
    • רשת האינטרנט
    • בניית אתרי אינטרנט
  • rss logo

    לכל המאמרים

    לכל המאמרים שפורסמו באינטרנט ישראל משנת 2008 ועד עכשיו.
  • rss logo

    RSS Feed

    משתמשים בקורא RSS? אם כן, עקבו אחרי אינטרנט ישראל באמצעות פיד ה-RSS!
    מה זה RSS?
  • Twitter logo

    עקבו אחרי בטוויטר

    בחשבון הטוויטר שלי אני מפרסם עדכונים מהירים על חדשות בתחום התכנות והיזמות, התרעות על מצבי חירום ורכילות בוערת על תחום הווב.
    מה זה טוויטר?
  • facebook like image

    ערוץ הטלגרם של אינטרנט ישראל

    בערוץ הטלגרם של אינטרנט ישראל אני מפרסם את הפוסטים של באתר וכן עדכונים טכנולוגיים נוספים.
    מה זה טלגרם?
  • github logo

    הפרויקטים שלי בגיטהאב

    הפרויקטים שאני כותב ושוחררו לציבור ברישיון קוד פתוח נמצאים ברובם בגיטהאב.
חיפוש

כל הזכויות שמורות לרן בר-זיק ולאינטרנט ישראל | מדיניות הפרטיות של אתר אינטרנט ישראל | אתר אינטרנט ישראל נגיש לפי תקן WCAG 2.0 AA | הצהרת הנגישות של האתר | אבטחת מידע ודיווח על בעיית אבטחת מידע

גלילה לראש העמוד