在 google 地图事件中访问 Backbone.View 函数

Access Backbone.View function within google maps event

所以我有一个 google 地图事件侦听器,我想在事件侦听器内的视图上调用一个函数。单击标记时,我不断收到未定义的错误。有任何想法吗? 这是所有代码:

APP = {};

APP.ArtPiece = Backbone.Model.extend({
    defaults: {
        first_name: 'First Name not provided',
        title: 'Title not provided',
        location: 'Location not provided',
        description: 'Description not provided',
        last_name: 'Last Name not provided',
        longitude: null,
        latitude: null,
        type: 'Type not provided',
        medium: 'Medium not provided'
    },
    initialize: function() {
        this.address();
    },
    address: function() {
        geocoder = new google.maps.Geocoder();
        console.log('In initialize');
        var latlng = new google.maps.LatLng(this.get('latitude'), this.get('longitude'));

        geocoder.geocode({'latLng': latlng}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
              if (results[1]) {
                console.log(results[1].formatted_address);
                return results[1].formatted_address;
              } else {
                console.log(status);
                return 'No address available';
              }
            } else {
              console.log(status);
              return 'No Address Provided. Google screwed us!';
            }
        });
    }
});

APP.ArtPieces = Backbone.Collection.extend({
    model: APP.ArtPiece,
    url: 'https://data.nashville.gov/resource/dqkw-tj5j.json'
});

APP.artPieces = new APP.ArtPieces();

APP.Map = Backbone.Model.extend({
    defaults: {
        center: new google.maps.LatLng(36.159480, -86.792112),
        zoom: 12,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
});

APP.map = new APP.Map();

APP.MapView = Backbone.View.extend({
    el: '#map',
    initialize: function () {
        this.collection.fetch({ reset: true });
        this.listenTo(this.collection, 'reset', this.render);
        this.map = new google.maps.Map(this.el, this.model.toJSON());
    },
    render: function () {
        var infoWindows = [];

        this.collection.each(function (artPiece) {

            var marker = new google.maps.Marker({
                map: this.map,
                position: new google.maps.LatLng(
                    artPiece.get('latitude'),
                    artPiece.get('longitude')
                ),
                title: artPiece.get('title'),
                markerId: artPiece.cid
            });

            var info = '<div class="info-window">' +
                       '<p class="artist"><strong>Artist: </strong>' +  artPiece.get('first_name') + ' '+ artPiece.get('last_name') + '</p>' +
                        '<p class="type"><strong>Type: </strong>' + artPiece.get('type') + '</p>' +
                        '<p class="medium"><strong>Medium: </strong>' + artPiece.get('medium') + '</p>' +
                        '<p class="description"><strong>Description: </strong>' + artPiece.get('description') + '</p>' +
                        '<p class="location"><strong>Location: </strong>' + artPiece.get('location') + '</p>' +
                        '<p class="address"><strong>Address: </strong>' + artPiece.get('address') + '</p>' +
                        '</div>';

            var infowindow = new google.maps.InfoWindow({
                content: info
            });

            infoWindows[infoWindows.length] = infowindow;

            google.maps.event.addListener(marker, 'click', function() {
                this.map.setZoom(14);
                this.map.setCenter(marker.position);
                for(i = 0;i<infoWindows.length; i++) { infoWindows[i].close(); }
                infowindow.open(this.map,marker);
                displayInformation(); //I want this to fire
            });
        }, this);
        $('#map').replaceWith(this.el);
        google.maps.event.addDomListener(window, 'load', initialize);
    },
    displayInformation: function() {
      //Do something
    }
});

APP.mapView = new APP.MapView({
    model: APP.map,
    collection: APP.artPieces
});

})();

在这个视图的底部,我在我希望函数触发的地方有注释:

render: function () {
    var infoWindows = [];

    this.collection.each(function (artPiece) {

        var marker = new google.maps.Marker({
            map: this.map,
            position: new google.maps.LatLng(
                artPiece.get('latitude'),
                artPiece.get('longitude')
            ),
            title: artPiece.get('title'),
            markerId: artPiece.cid
        });

        var info = '<div class="info-window">' +
                   '<p class="artist"><strong>Artist: </strong>' +  artPiece.get('first_name') + ' '+ artPiece.get('last_name') + '</p>' +
                    '<p class="type"><strong>Type: </strong>' + artPiece.get('type') + '</p>' +
                    '<p class="medium"><strong>Medium: </strong>' + artPiece.get('medium') + '</p>' +
                    '<p class="description"><strong>Description: </strong>' + artPiece.get('description') + '</p>' +
                    '<p class="location"><strong>Location: </strong>' + artPiece.get('location') + '</p>' +
                    '<p class="address"><strong>Address: </strong>' + artPiece.get('address') + '</p>' +
                    '</div>';

        var infowindow = new google.maps.InfoWindow({
            content: info
        });

        infoWindows[infoWindows.length] = infowindow;

        google.maps.event.addListener(marker, 'click', function() {
            this.map.setZoom(14);
            this.map.setCenter(marker.position);
            for(i = 0;i<infoWindows.length; i++) { infoWindows[i].close(); }
            infowindow.open(this.map,marker);
            displayInformation(); //I want this to fire
        });
    }, this);
    $('#map').replaceWith(this.el);
    google.maps.event.addDomListener(window, 'load', initialize);
},
displayInformation: function() {
  //Do something
}

可能最简单的方法是将视图存储在局部变量中,然后调用 displayInformation

var mapView = this;
google.maps.event.addListener(marker, 'click', function() {
    this.map.setZoom(14);
    this.map.setCenter(marker.position);
    for(i = 0;i<infoWindows.length; i++) { infoWindows[i].close(); }
    infowindow.open(this.map,marker);
    mapView.displayInformation();
});

当您同时需要别人指定的 this(即您不能使用绑定函数)和您自己选择的 this 时,这是一个非常标准的技巧.

演示:https://jsfiddle.net/ambiguous/jg58het3/