質問

Google Maps v3 用に作成したモジュールがあり、Backbone.js ビュー コンストラクターに変換しようとしています。

これまでのビューモジュールは次のとおりです。コードの後で発生する問題について説明します。

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);
  }

});

私が抱えている問題は、Google マップのイベント リスナーと「this」の処理方法にあります。

当初は、dragMarker メソッドと dragMap メソッドはなく、代わりに次の 2 つが初期化ブロック内にありました。

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);
});

この最初のアプローチで私が遭遇した問題は、これらの匿名関数内の "this" がそれぞれ "this.marker" と "this.map" を参照していることです。この最初のアプローチの問題は、最初のリスナーでは「this.map」を参照する方法がないため、panTo() を実行できないことでした。2 番目のリスナーでは、「this.marker」を参照する方法がなかったため、setPosition() を使用してそのマーカーの周囲にマップを再配置することができませんでした。

次に、リスナー内の匿名関数を取り出してビューのメソッドとして宣言し、 _.bindAll(this, "dragMarker", "dragMap"); を実行できると考えました。

このアプローチの問題は、次のようにイベント ブロックにリスナーを記述しなければならないことです。

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

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

これは、newmap = new pg.views.CreateMap; でコンストラクターを呼び出したときを意味します。「this.dragMarker()」と「this.dragMap()」は、「dragend」イベントがトリガーされたときにコールバックとして評価されるのではなく、すぐに評価されることを確認します。

問題ないと思い、これらを次のように匿名関数でラップしました。

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

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

残念ながら、これにより、「this.dragMarker」の「this」が私が構築した親オブジェクトを参照しなくなり、代わりに「this.marker」を再度参照するという以前の問題に戻ります。2 番目のリスナーでも同じ問題が発生します。

ここで完全に行き詰まってしまいました。これを解決する方法について何かアイデアがある人はいますか?

役に立ちましたか?

解決

呼び出される匿名関数を取得します dragend そして明示的にバインドします。

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

こちらです this コンテキスト外で呼び出された場合でも、常に CreateMap に関連付けられます。

他のヒント

私は、JavaScript で一般的な that/self ハックを使用して、この問題を解決しました。

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);
});

このハックを必要としない解決策を持っている人がいたら、私は大歓迎です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top