2015-05-24 3 views
0

Я создаю веб-приложение jQuery/javascript, используя jQuery .prototype. В следующем коде я хочу обновить до прототипов глобальное значение this.score, мне нужно будет bind(this), чтобы сделать эту работу.

Без привязки this Я могу достичь пролета внутри btnElement с $(this), но после привязки это больше не работает. Есть ли какое-либо обходное решение для чего-то вроде этого? ;)

showQuestion: function(question) { 
    this.quiz.show(); 

    var btnElement = this.quiz.find('div'); 
    btnElement.on('click', function() { 
     var btn = $(this).find('span'); 

     if (btn.hasClass('correct')) { 
      btn.addClass('good'); 
      this.score += 1; 
     } else { 
      $('span.correct').addClass('good'); 
      btn.addClass('wrong'); 
     } 
    }.bind(this)); 
} 

ответ

4

Вы обязаны свой обратный вызов событий, так this в это относится к тому, что this вне его называют. Это означает, что вы не можете использовать обычный смысл. this имеет в обработчиках событий jQuery (элемент DOM, связанных с событием).

Три способа обработки, что:

  1. Используйте btnElement вместо этого, так как у вас есть под рукой:

    showQuestion: function(question) { 
        this.quiz.show(); 
    
        var btnElement = this.quiz.find('div'); 
        btnElement.on('click', function() { 
         var btn = btnElement.find('span'); // <==== 
    
         if (btn.hasClass('correct')) { 
          btn.addClass('good'); 
          this.score += 1; 
         } else { 
          $('span.correct').addClass('good'); 
          btn.addClass('wrong'); 
         } 
        }.bind(this)); 
    } 
    
  2. Использование e.currentTarget, что это то же самое this бы, если обработчик не были связаны (в этом случае вы также можете использовать e.delegateTarget, потому что это не делегированный обработчик, и поэтому это то же значение):

    showQuestion: function(question) { 
        this.quiz.show(); 
    
        var btnElement = this.quiz.find('div'); 
        btnElement.on('click', function(e) {    // <==== 
         var btn = $(e.currentTarget).find('span'); // <==== 
    
         if (btn.hasClass('correct')) { 
          btn.addClass('good'); 
          this.score += 1; 
         } else { 
          $('span.correct').addClass('good'); 
          btn.addClass('wrong'); 
         } 
        }.bind(this)); 
    } 
    

    Я не рекомендовал e.target, потому что это не совсем то же самое: e.target является элементом, где произошло событие; this - это элемент, на котором вы зацепились. Таким образом, e.target может быть потомок элемент вашей викторины div.

  3. Не связывайте обработчик событий, и вместо того, чтобы хранить ссылку на this в переменной обработчик события закрывается через:

    showQuestion: function(question) { 
        var self = this;      // <==== 
    
        self.quiz.show(); 
    
        var btnElement = this.quiz.find('div'); 
        btnElement.on('click', function() { 
         var btn = $(this).find('span'); 
    
         if (btn.hasClass('correct')) { 
          btn.addClass('good'); 
          self.score += 1;    // <==== 
         } else { 
          $('span.correct').addClass('good'); 
          btn.addClass('wrong'); 
         } 
        });          // <==== 
    } 
    
+1

Вместо 'e.target', это должно быть' e.delegateTarget', я думаю –

+0

@ A.Wolff: Ooooh! Я всегда забываю о 'delegateTarget' jQuery! –

+1

@ A.Wolff: Хотя на самом деле 'e.currentTarget' был бы наиболее подходящим, но я всегда забываю о' currentTarget', так что еще раз спасибо. Но да, 'e.delegateTarget' совпадает с' e.currentTarget' в не делегированном обработчике. –

2

Одним из способов является НЕ связывать и использовать ссылка на this вне обработчика щелчка

showQuestion: function(question) { 
    this.quiz.show(); 

    var btnElement = this.quiz.find('div'); 
    var self = this; // create a reference to this 
    btnElement.on('click', function() { 
     var btn = $(this).find('span'); // you will still be able to find the span which is inside the btnElement 

     if (btn.hasClass('correct')) { 
      btn.addClass('good'); 
      self.score += 1; // you will still be able to refer this which is reference as self outside 
     } else { 
      $('span.correct').addClass('good'); 
      btn.addClass('wrong'); 
     } 
    }); 
} 

Другой способ отправить параметр в bind(помимо всех других вариантов в других ответов)

showQuestion: function(question) { 
    this.quiz.show(); 

    var btnElement = this.quiz.find('div'); 
    btnElement.on('click', function(event, btnElement) { // 
     var btn = btnElement.find('span'); 
     if (btn.hasClass('correct')) { 
      btn.addClass('good'); 
      this.score += 1; 
     } else { 
      $('span.correct').addClass('good'); 
      btn.addClass('wrong'); 
     } 
    }.bind(this, btnElement)); 
} 

Это тоже работает только, что это немного странно, чтобы отправить ссылку на кнопку, чтобы его собственный обработчик щелчка.

+0

Удивительный обходной путь, спасибо за решение моей проблемы! ;) – ronnyrr

Смежные вопросы