7

Tengo un módulo que creé para Google Maps v3 que estoy tratando de convertir en un constructor de vista Backbone.js.Backbone.js con Google Maps - problemas con esto y los oyentes

Aquí es mi opinión módulo hasta el momento: voy a explicar los problemas que tengo después del código:

pg.views.CreateMap = Backbone.View.extend({ 

    tagName: "div", 
    className: "map", 

    events: {}, 

    latitude: "-23.56432", 
    longitude: "-46.65183", 

    initialize: function() { 
    _.bindAll(this, 'render', 'dragMarker', 'dragMap'); 

    this.latlng = new google.maps.LatLng(this.latitude, this.longitude); 
    var myOptions = { 
     zoom: 16, 
     center: this.latlng, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
    }; 
    this.map = new google.maps.Map($(this.el)[0], myOptions); 
    this.marker = new google.maps.Marker({ 
     map: this.map, 
     position: this.latlng, 
     draggable: true 
    }); 

    google.maps.event.addListener(this.marker, "dragend", this.dragMarker()); 

    google.maps.event.addListener(this.map, "dragend", this.dragMap()); 

    }, 

    render: function() { 
    return this; 
    }, 

    dragMarker: function() { 
    this.latlng = this.marker.getPosition(); 
    this.map.panTo(this.latlng); 
    }, 

    dragMap: function() { 
    this.latlng = this.map.getCenter(); 
    this.marker.setPosition(this.latlng); 
    } 

}); 

El problema que estoy teniendo es con los detectores de eventos mapas de Google y cómo "este" es manejado.

que originalmente no tenía los métodos dragMarker y dragMap y en lugar de estos dos en el bloque de inicialización:

google.maps.event.addListener(this.marker, "dragend", function() { 
    this.latlng = this.marker.getPosition(); 
    this.map.panTo(this.latlng); 
}); 

google.maps.event.addListener(this.map, "dragend", function() { 
    this.latlng = this.map.getCenter(); 
    this.marker.setPosition(this.latlng); 
}); 

El problema que encontré con este primer enfoque es que "este" dentro de esas funciones anónimas que se refiere "this.marker" y "this.map" respectivamente. El problema con este primer enfoque fue que, en el primer oyente, no tenía forma de referirme a "this.map" y, por lo tanto, no podía realizar un panTo(). Con el segundo oyente, no tuve forma de referirme a "this.marker" y por lo tanto no pude volver a centrar el mapa alrededor de ese marcador usando setPosition().

Pensé entonces que podía sacar las funciones anónimas en los oyentes y declararlas como métodos de la vista, que luego realizaría _.bindAll (esto, "dragMarker", "dragMap");

El problema con este enfoque es que entonces yo tenía que escribir los oyentes en el bloque de eventos, así:

google.maps.event.addListener(this.marker, "dragend", this.dragMarker()); 

google.maps.event.addListener(this.map, "dragend", this.dragMap()); 

Esto significa que cuando llamé al constructor con newmap = new pg.views.CreateMap; que el "this.dragMarker()" y "this.dragMap()" se evaluaron inmediatamente en lugar de evaluarse como una devolución de llamada cuando se desencadena el evento "dragend".

Ningún problema pensé y luego se envuelve aquellos en funciones anónimas, así:

google.maps.event.addListener(this.marker, "dragend", function() { 
    this.dragMarker(); 
}); 

google.maps.event.addListener(this.map, "dragend", function() { 
    this.dragMap(); 
}); 

Desafortunadamente Esto también me lleva de vuelta a un problema anterior que el "presente" en "this.dragMarker" no se refiere al objeto principal que construí, pero en su lugar refiérase a "this.marker" nuevamente. El mismo problema ocurre con el segundo oyente.

Estoy completamente atrapado aquí. Alguien tiene alguna idea sobre cómo puedo resolver esto?

+0

La forma correcta de adjuntar controlador de eventos es la siguiente: 'google.maps.event.addListener (this.marker," dragend ", this.dragMarker);' (sin los paréntesis). Pero esto no resolverá tu problema de contexto. –

Respuesta

6

Tome las funciones anónimas llamadas en dragend y enlace explícitamente.

_.bindAll(this, 'dragMarker', 'dragMap'); 
google.maps.event.addListener(this.marker, "dragend", this.dragMarker); 
/* etc ... */ 

De esta manera this siempre estarán ligados a CreateMap incluso si se llama fuera de contexto.

+0

en dragMarker: function() {}, ¿cómo puedo obtener esto de google.maps.event – nXqd

5

He resuelto este problema mediante el uso de ese/self hack común en Javascript.

var self = this; 

google.maps.event.addListener(this.marker, "dragend", function() { 
    self.latlng = this.getPosition(); 
    self.map.panTo(self.latlng); 
}); 

google.maps.event.addListener(this.map, "dragend", function() { 
    self.latlng = this.getCenter(); 
    self.marker.setPosition(self.latlng); 
}); 

Si alguien tiene una solución que no requiere este truco, soy todo oídos.

+0

No es realmente un truco, es lo que habría hecho. –

+0

no es un truco. Dougl Crockford habla de var que = esto; en sus videos de YUI. – jspooner

+0

Actualmente uso el enfoque _.bind(). Encuentro que es mucho más limpio y hay menos posibilidades de arruinar (como olvidar poner var delante de uno mismo = esto, por ejemplo) –

Cuestiones relacionadas