אופטימיזצית אירועים ב-jQuery

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

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

bind

לדוגמה:


$('#nav a').bind('click', function(e) {
  e.preventDefault();
});

בעבר זו היתה הדרך היחידה להצמיד אירועים באמצעות jQuery, פשוט בוחרים את האלמנט המתאים ומצמידים לו את האירוע. זו דרך פשוטה מאד. החסרון המרכזי שלה – אם יש אלמנטים רבים, מנוע ה-JavaScript צריך להצמיד אירוע לכל אלמנט בנפרד. ההשפעה על הביצועים, כפי שאתם יכולים לדמיין, היא כמו השפעת תמונה של רוזאן בר בעירום על שחקן פורנו (לא השפעה טובה).

הצמדת אירוע באמצעות קיצור ל-bind

לדוגמה:


$('#nav a').click(function(e) {
  e.preventDefault();
});

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

delegate

לדוגמה:


$('#nav').delegate('a', 'click', function(e) {
  e.preventDefault();
});

השיטה הזו נכנסה לגרסה 1.4.3 ונכון לגרסה 1.7 ממליצים שלא להשתמש בה אלא להשתמש ב-on. אבל חשוב מאד לעבור עליה כי שווה להכיר את הקונספט מאחוריה לשימוש ב-on. באופן עקרוני, על מנת להשתמש ב-delegate, אנו צריכים את אלמנט אב כלשהו ואת האלמנט שאליו אנו צריכים להצמיד את האירוע. מה שה-delegate עושה זה להצמיד את האירוע לאלמנט האב וכאשר האירוע מופעל, אז לשאול את האירוע מי הפעיל אותו ואם זה האלמנט הנכון – להפעיל את מה שאנחנו רוצים.
מסובך? בואו ונסביר שוב – נניח ויש לי div חביב שבו יש מיליון input שלכל אחד מהם יש id שונה. במקום להצמיד אירוע לכל input, אני יכול להצמיד אירוע ל-div החביב, לחיצה על אחד ה-input תפעיל את האירוע של ה-div (כי ב'תכלס לחצתי בתוך ה-div), בתוך האירוע אני שואל – מי ה-input שעליו לחצתי ולפעול בהתאם לזהות ה-input.

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

live

לדוגמה:


$('#nav a').live('click', function(e) {
  e.preventDefault();
});

זו פונקציה שנכנסה החל מגרסה 1.3, היא זהה למדי ל-bind, אבל יש בה טוויסט – היא מצמידה אירועים לאלמנטים גם בעתיד ולא רק בהווה. מה זאת אומרת? נניח ואני עשיתי bind לאירוע קליק לקישור ואחרי שעשיתי bind יצרתי אלמנט מסוג קישור, ה-bind לא יתפוס, כי הוא מתיחס רק לאלמנטים בהווה. אם אני משתמש ב-live הוא יתפוס.
איך jQuery עושה את זה? היא פשוט עושה delegate ל-body (או לאלוהים יודע איזה אלמנט אב) ותופסת את האלמנטים שפירטנו ב-live. איך זה מבחינת יעילות? יעיל בהרבה מ-bind, ולו רק בגלל שלא צריך לבצע הצמדת אירועים למלא אלמנטים, אבל פחות יעיל מ-delegate, כי delegate משתמש בהכרח באלמנט אב נמוך יותר מאלמנט האב הכללי של live.

אפשר לנסות וליעל את live באמצעות שטיקים שונים כמו שימוש ב-each:


$('#nav').each(function() {
  $('a', this).live('click', function(e) {
    e.preventDefault();
  });
});

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

שימוש ב-on

החל מגרסה 1.7 יש לנו את on שהיא נכון לעכשיו השיטה היעילה ביותר להצמדת אירועים:


$('#nav').on('click', 'a', function(e) {
  e.preventDefault();
});

זו שיטה שבעצם משלבת את כל היתרונות של live ו-delegate ונכון לעכשיו היא היעילה והמהירה ביותר מבין כל השיטות. כמובן שעלינו לבחור אלמנט אב ספציפי ולא body או משהו דומה כיוון שאז, כפי שראינו בהבדל בין היעילות של delegate ל-live, אנחנו לא מרוויחים דבר.

אז למה בעצם לא לכתוב 'תשתמשו תמיד ב-on' במקום להכריח אתכם לקרוא 500 מילים על השיטות השונות? ראשית, לא כולם משתמשים בגרסה 1.7. שנית, חשוב להבין מה זה event delegation ולמה בדיוק on עובד יותר מהר – בכך שאנחנו בעצם לא מצמידים אירוע לכל אלמנט ומצמידים אירוע רק לאלמנט האב. מההבנה הזו אנו גם יכולים להסיק כיצד ליצור on יותר מהיר.

כיוון שאסור לכם להאמין לי סתם כך, אני מצרף קישור למבחן הרלוונטי ב-jsperf שהוא כלי נהדר לבחינת ביצועים של JavaScript. אני מודה בהכנעה שבדקתי בעיקר בכרום – הנה התוצאות בגרף:

השוואת יעילות בין הצמדות אירועים ב-jQuery

השוואת יעילות בין הצמדות אירועים ב-jQuery

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

אהבתם? לא אהבתם? דרגו!

לא אהבתי בכלללא אהבתיבסדראהבתיאהבתי מאוד (1 הצבעות, ממוצע: 5.00 מתוך 5)


אל תשארו מאחור! יש עוד מה ללמוד!