Backbone.js con Google Maps - problemi con questo e gli ascoltatori
-
09-10-2019 - |
Domanda
Ho un modulo che ho creato per Google Maps v3 che sto cercando di convertire in una visione costruttore Backbone.js.
Ecco il mio modulo di vista finora: mi spiego i problemi che sto avendo dopo il codice:
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);
}
});
Il problema che sto avendo è con gli ascoltatori di eventi di Google Maps e su come "questo" è gestita.
Io inizialmente ho non ho i metodi dragMarker e dragMap e invece questi due nel blocco di inizializzazione:
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);
});
Il problema che ho riscontrato con questo primo approccio è che "questo" all'interno di quelle funzioni anonime denominato "this.marker" e "this.map", rispettivamente. Il problema con questo primo approccio è che nel primo ascoltatore, ho avuto modo di riferirsi a "this.map" e quindi non poteva eseguire un panto (). Con il secondo ascoltatore, non ho avuto modo di riferirsi a "this.marker" e quindi non poteva centrare nuovamente la mappa intorno a quel marcatore utilizzando setPosition ().
Ho poi pensato che ho potuto tirare le funzioni anonime negli ascoltatori e dichiarare come metodi di visualizzazione, che avrei poi eseguire un _.bindAll (questo, "dragMarker", "dragMap");
Il problema di questo approccio è che ho poi dovuto scrivere gli ascoltatori nel blocco evento in questo modo:
google.maps.event.addListener(this.marker, "dragend", this.dragMarker());
google.maps.event.addListener(this.map, "dragend", this.dragMap());
Questo significava che quando ho chiamato il costruttore con newmap = new pg.views.CreateMap; che il "this.dragMarker ()" e "this.dragMap ()" sono stati valutati immediatamente invece di essere valutato come un callback quando viene attivato l'evento "dragend".
Nessun problema ho pensato e poi avvolto quelli in funzioni anonime in questo modo:
google.maps.event.addListener(this.marker, "dragend", function() {
this.dragMarker();
});
google.maps.event.addListener(this.map, "dragend", function() {
this.dragMap();
});
Purtroppo questo porta anche a me di nuovo ad un problema in precedenza che il "questo" in "this.dragMarker" non si riferisce all'oggetto genitore ho costruito, ma invece fare riferimento a "this.marker" di nuovo. Lo stesso problema si verifica con il secondo ascoltatore.
Sono completamente bloccato qui. Qualcuno ha qualche idea su come posso risolvere questo?
Soluzione
Prendere le funzioni anonime invitato dragend
e si legano in modo esplicito.
_.bindAll(this, 'dragMarker', 'dragMap');
google.maps.event.addListener(this.marker, "dragend", this.dragMarker);
/* etc ... */
Questa this
modo sarà sempre legato a CreateMap anche se chiamato fuori dal contesto.
Altri suggerimenti
Ho risolto questo problema utilizzando il che / sé mod comune in 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);
});
Se qualcuno ha una soluzione che non richiede questo hack, sono tutto orecchi.