שילוב רכיבי React ביישום Backbone

03/09/2015

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

Backbone עבורי היתה אהבה ממבט ראשון. אחרי שנים עם jQuery וקוד שתמיד מצא דרכים לא צפויות להסתבך, מישהו סיפר לי על ספריה מופלאה שתאפשר לכתוב יישומים גדולים בצורה מסודרת, בלי להפריע יותר מדי. זה עבד טוב ומהר מאוד רוב הקוד שכתבתי השתמש בספריה זו. לימים הרגשתי שהמודלים של Backbone הם נפלאים, אבל כשזה מגיע ל Views יש מקום לשיפור. אבל רק כשהתחלתי לכתוב ריאקט הבנתי את כל הדברים שהפריעו לי ב Backbone. 

דוגמא? ברור. הנה View פשוט ב Backbone וגירסת ריאקט שלו. נתחיל עם הקוד ואז נדבר על ההבדלים.

1. תיבת טקסט עם ספירת אותיות ב Backbone

הרכיב הוא תיבת טקסט המציגה כמה אותיות יש בתיבה. כך זה נראה יחד עם הקוד:

אנחנו נתמקד ב View ונתחיל עם מה שטוב: ניהול האירועים מאוד מסודר, יש מקום אחד שממפה בין אירועי ה DOM שהרכיב מייצר לפונקציות הטיפול בהם. כל שינוי במודל מזוהה ומביא לעדכון הרכיב בהתאם ורוב הפונקציות מאוד פשוטות. מה שלא אהבתי זו פונקציית render. הנה הקוד שלה:

render: function() {

    var state = {
      text: this.model.toJSON().text,
      count: this.model.toJSON().text.length
    };

    if ( ! this.$el.html() ) {
      this.initDOM(state);
    }

    var $ta = $('textarea', this.$el);
    var $count = $('p', this.$el);

    $ta.val(state.text);
    $count.html(this.templateCount(state));

    return this;
  }

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

 

2. אותה התיבה בגירסת React

נשארתי עם המודל אבל הפעם החלפתי את ה View של Backbone ברכיב של ריאקט. כך זה נראה עם הקוד:

ההפתעה הראשונה למי שלא רגיל לריאקט היא המעבר ל JSX. שימו לב שאלמנטי ה HTML הכתובים בתוך קובץ ה JavaScript כבר לא כתובים כמחרוזת אלא כחלק מהקוד. למעשה קובץ ה js עובר כעת המרה מיוחדת לפני שליחתו לדפדפן המחליפה את תגיות ה HTML בקוד לכל דבר. העובדה שלא צריך לשרשר מחרוזות הופכת את הקוד ליציב יותר.
אבל זה לא נגמר כאן: למעשה השינוי הגדול ביותר הוא שנפטרנו מהיומנאות. אין יותר צורך בפונקציית render לבדוק מה המצב הקיים ולהתאים את מנגנון העדכון. במקום, אנו פשוט מספרים איך אנו רוצים שדברים יראו, וריאקט כבר ישבור את הראש איך לעדכן את התצוגה בצורה היעילה ביותר.

שאר הקוד נותר פחות או יותר ללא שינוי, מלבד שינויי שמות הכרחיים כתוצאה מהחלפת הספריות (initialize למשל הפכה ל componentDidMount). 

 

3. האם זה היה שווה את המאמץ?

פונקציית ה render החדשה נראית כך:

  render: function() {
    var text = this.state.text;
    var count = this.state.text.length;

    return <div>
      <textarea onChange={this.textChanged} value={text}></textarea>
      <button className="btn-reset" onClick={this.revert}>Revert</button>
        <p>You typed {count} characters in the box</p>
      </div>
  },

היא קצרה יותר, מטפלת בפחות מקרים וכוללת בתוכה את כל מה שצריך לדעת על איך הרכיב נראה (ללא תבניות חיצוניות) וגם על האירועים בהם הרכיב מטפל. פונקציה זו מחליפה גם את ה render המקורית, גם את הפונקציה initDOM והבדיקה האם צריך להפעילה, גם את השדה events וגם את שתי התבניות. הקוד החדש הרבה יותר קל לתחזוקה ולבדיקה. מה שהכי נחמד זה שאפשר לעשות את ההמרה לאט, View אחרי View. כל שאר היישום נשאר ללא שינוי.