2008-10-23 17 views
19

Existe-t-il une méthode recommandée ou courante dans JavaScript pour que les membres de la classe soient des gestionnaires d'événements?Méthodes de classe en tant que gestionnaires d'événements dans JavaScript?

Prenons l'exemple simple:

<head> 
    <script language="javascript" type="text/javascript"> 

     ClickCounter = function(buttonId) { 
      this._clickCount = 0; 
      document.getElementById(buttonId).onclick = this.buttonClicked; 
     } 

     ClickCounter.prototype = { 
      buttonClicked: function() { 
       this._clickCount++; 
       alert('the button was clicked ' + this._clickCount + ' times'); 
      } 
     } 

    </script> 
</head> 
<body> 
    <input type="button" id="btn1" value="Click me" /> 
    <script language="javascript" type="text/javascript"> 
     var btn1counter = new ClickCounter('btn1'); 
    </script> 
</body> 

Le gestionnaire d'événements ButtonClicked est appelé, mais le membre _clickCount est inaccessible ou ce point à un autre objet.

des astuces/articles/ressources sur ce genre de problèmes?

Répondre

17
ClickCounter = function(buttonId) { 
    this._clickCount = 0; 
    var that = this; 
    document.getElementById(buttonId).onclick = function(){ that.buttonClicked() }; 
} 

ClickCounter.prototype = { 
    buttonClicked: function() { 
     this._clickCount++; 
     alert('the button was clicked ' + this._clickCount + ' times'); 
    } 
} 
+0

Merci pour votre solution. Je tente aussi de comprendre la plus grande image - modèles, pratiques, etc. Tous les bons articles que vous connaissez? – JacobE

+5

cette chose est grande: http://ejohn.org/apps/learn/ – pawel

+8

Ceci est un bon exemple, mais cette réponse est peut-être mieux avec quelques explications pour expliquer pourquoi il est une bonne solution pour les novices ici. –

5

Une fonction attachée directement à la propriété onclick aura le pointage de la propriété de contexte d'exécution this à l'élément.

Lorsque vous avez besoin d'un événement d'élément à exécuter sur une instance spécifique d'un objet (à la déléguée dans .NET), vous aurez besoin d'une fermeture: -

function MyClass() {this.count = 0;} 
MyClass.prototype.onclickHandler = function(target) 
{ 
    // use target when you need values from the object that had the handler attached 
    this.count++; 
} 
MyClass.prototype.attachOnclick = function(elem) 
{ 
    var self = this; 
    elem.onclick = function() {self.onclickHandler(this); } 
    elem = null; //prevents memleak 
} 

var o = new MyClass(); 
o.attachOnclick(document.getElementById('divThing')) 
+0

C'est exactement ce que je cherchais! Je vous remercie! – Jeremy

0

Je ne sais pas pourquoi Function.prototype.bind n'a pas été mentionné ici pour le moment. Je vais donc laisser cela ici;)

ClickCounter = function(buttonId) { 
    this._clickCount = 0; 
    document.getElementById(buttonId).onclick = this.buttonClicked.bind(this); 
} 

ClickCounter.prototype = { 
    buttonClicked: function() { 
     this._clickCount++; 
     alert('the button was clicked ' + this._clickCount + ' times'); 
    } 
} 
1

Vous pouvez utiliser la syntaxe de graisse flèche, qui se lie au champ lexical de la fonction

function doIt() { 
    this.f =() => { 
    console.log("f called ok"); 
    this.g(); 
    } 
    this.g =() => { 
    console.log("g called ok"); 
    } 
} 

Après cela, vous pouvez essayer

var n = new doIt(); 
setTimeout(n.f,1000); 

Vous pouvez l'essayer sur babel ou si votre navigateur prend en charge ES6 sur jsFiddle.

Malheureusement, la -syntax ES6 classe ne semble pas permettre la création de la fonction lexicalement binded à ce sujet. Personnellement, je pense que ça pourrait aussi bien faire ça. EDIT: Il semble y avoir experimental ES7 feature to allow it.