2011-01-03 15 views
1

Ich schreibe ein Plugin für jQuery und ich habe ein Chaos in meinem Kopf mit dem Kontext Problem in Javascript.jQuery Plugin, Kontext und setTimeout

Dies ist eine vereinfachte Version meiner Plugin:

(function($){ 

$.fn.myplugin = function(options){ 
    return new MyPlugin(this, options); 
}; 


function MyPlugin(el, o) 
{ 
    this.root = el; 
    this.input_box = el.find('#the_input'); 
    this.map = null; 
    this.timeout = null; 
    var self = this; 

    self.input_box.keyup(function(){ 
    if(self.timeout!==null) 
    { 
     clearTimeout(self.timeout); 
    } 
    self.timeout = setTimeout(function(){ 
      self.search_address(self); 
      }, 500); 
    }); 
} 

MyPlugin.prototype = { 

    search_address : function(context){ 
      geocoder.geocode({'address':$('#direction').val()}, 
      function(results, status){ 
       var lat = results[0].geometry.location.lat(); 
       var lng = results[0].geometry.location.lng(); 
       var latlng = new google.maps.LatLng(lat, lng); 

       context.select_address(latlng, '');         
    }, 

    select_address : function(latlng, text){ 
     self.root.find('#url').val('http://maps.google.com/?q='+encodeURI($('#direccion').val())+'&ll='+coords.lat()+','+coords.lng()+'&ie=UTF8&oe=UTF8&z=18'); 
    } 
}; 
})(jQuery); 

Ich habe gelesen, dass setTimeout den Kontext auf das globale Objekt setzt, so habe ich die Schließung der Lage sein, den Kontext zu search_address Funktion zu übergeben. Dadurch konnte ich select_address aus dem Rückruf in geocode Funktion aufrufen, aber dieser Rückruf ruft select_address und dort ist der Kontext wieder unerwünscht: self.root wird nicht gefunden.

Ich bin völlig verloren, wie den Kontext zu behandeln, obwohl ich, dass die var self=this bei der Initialisierung des „Objekt“ mit Ich würde diese Probleme vermeiden ...

ich beachten muss, dass select_address aufgerufen werden können direkt ...

Antwort

1

Verwenden this an diesem Punkt auf den aktuellen Kontext beziehen:

select_address : function(latlng, text){ 
    this.root.find('#url').val('http://maps.google.com/?q='+encodeURI($('#direccion').val())+'&ll='+coords.lat()+','+coords.lng()+'&ie=UTF8&oe=UTF8&z=18'); 
} 
+0

Warum funktioniert das nicht dort? Denken Sie daran, dass select_address direkt aufgerufen werden kann ... Ich würde gerne eine Regel kennen, um das zu umgehen und Versuch und Irrtum zu vermeiden. –

+0

'self' ist eine Variable, die Sie haben, aber sie ist nicht im aktuellen Bereich vorhanden. Wenn Sie den aktuellen Kontext benötigen, können Sie 'this' verwenden, Sie verwenden einfach einen Referenzhalter wie' self', wenn 'this' sich ändern kann, wie in einem Callback, den Sie nicht kontrollieren. –

+0

Also sollte ich eine "self" var an einer beliebigen Stelle erstellen, an der sich der Kontext ändern kann, und sich nicht auf das im Initialisierer erstellte selbst verlassen kann ... Also ist es eine gute Übung, einen Kontext an Callbacks zu übergeben? –

1

ich nur etwas kühl fand heraus, dass die SetTimeout Kontext in jQuery 1.4+ behebt.

Sie können die jQuery.proxy verwenden, um das Kontextproblem zu lösen.

Hier ist mein Code:

 

    Application = function() 
    { 
     this.AMethod = function(){}; 

     setTimeout($.proxy(this.AMethod,this), 100); 


    } 

Nach dem Ablauf dieser Zeit wird die Application.AMethod ausgeführt und damit die „Anwendung“ Kontext

LE gehalten wird: Alternativelly Sie Ihre eigene Proxy-Funktion erstellen sehr einfach, wenn Sie nicht möchten, dass Ihr Plugin nur auf jQuery 1.4+ beschränkt ist:

 

    function proxy(func, context) 
    { 
     return function(){ return func.apply(context, arguments);} 
    } 

Verwandte Themen