Backbone.js События не срабатывают - PullRequest
1 голос
/ 22 февраля 2012

У меня есть вид, который я могу загрузить. Однако события не стреляют. Вот вид:

MapModalView = Backbone.View.extend({
events: {
    'click #closeMapModal': 'closeModal',
    'click #modal_streetview': 'renderStreet'
},
initialize: function(){
    this.el = $('.modal_box');
    this.template = _.template($('#map-modal-template').html());
    _.bindAll(this, 'renderMap', 'renderPin');
},

render: function(){
    $(this.el).show().append(this.template({
        model: this.model
    }));
    this.renderMap();
    this.renderPin();
},
renderMap: function(){
    this.thisLat = _this.model.get('lat');
    this.thisLng = _this.model.get('lng');
    this.modalMap = new google.maps.Map(document.getElementById('modalMap'), {
        zoom : 12,
        center : new google.maps.LatLng(this.thisLat, this.thisLng), // VANCOUVER
        mapTypeId : google.maps.MapTypeId.ROADMAP
    });
},
renderPin: function(){
    marker = new google.maps.Marker({
        position : new google.maps.LatLng(this.thisLat, this.thisLng),
        map : this.modalMap,
        animation : google.maps.Animation.DROP,
        icon : '/img/lazy-pin.png'
    });        
},
renderStreet: function(e){
    e.preventDefault();
    this.modalMap.getStreetView().setPosition(this.modalMap.center);
    this.modalMap.getStreetView().setVisible(true);
},
closeModal: function(e){
    alert('hello');
    e.preventDefault();
    $(this.el).hide().find('div').remove();
}

})

Я удалил одну из функций события, потому что это было не важно. В любом случае, это представление инициализируется в моем маршрутизаторе:

    this.mapModalView = new MapModalView();

И у меня есть представление всплывающей подсказки, внутри которого есть событие, которое вызывает функцию рендеринга из ModalMapView. Вот этот вид:

ToolTipView = Backbone.View.extend({
initialize: function() {
    this.template = _.template($('#toolTip').html());
    this.mapTemplate = _.template($('#map-modal-template').html());
    this.model.bind('change:tooltip', this.toggleTooltip, this);
    return this;
},

events: {
    'mouseenter': 'toolTipOn',
    'mouseleave': 'toolTipOff',
    'click #show-restaurant-map': 'mapModal'
},

mapModal: function(){
    router.mapModalView.render(this.model);
},

render: function() {
    $(this.el).html(this.template({
        model: this.model
    }));
    this.delegateEvents();
    return this;

}

});

Я удалил функции, которые я не считал важными, снова выше.

Также вот мой шаблон:

<script type="text/template" id="map-modal-template">
<div id="map_modal">
    <button title="Close" id="closeMapModal" class="right">Close</button>
    <h3>Restaurant Map &amp; Access Information</h3>
    <ul>
        <li><a href="#" title="Map View" id="modal_mapview">Map</a></li>
        <li><a href="#" title="Street View" id="modal_streetview">Street View</a></li>
        <li><a href="#" title="Parking &amp; Access Info" id="modal_parking">Parking &amp; Access Info</a></li>
    </ul>
    <div id="modalMap"></div>
</div>
</script>

и, конечно, моя HTML-разметка на странице, над которой я работаю:

<div class="modal_box"></div>

Ответы [ 2 ]

3 голосов
/ 22 февраля 2012

Я не вижу ни одного _this, определенного где-либо, поэтому я ожидал бы, что все остановится, как только вы позвоните renderMap, и это помешает вашим событиям что-либо делать.

Я вижу это:

MapModalView = Backbone.View.extend({
    //...
    _this: this,

, но это не создает _this в области видимости объекта, а просто создает значение по умолчанию this._this для экземпляров вашего представления;Более того, когда строится MapModalView, this, вероятно, будет window, поэтому все, что вы делаете, это даете каждому MapModalView ссылку на window в this._this.

Я думаю, что все ваши _this ссылки должны быть this, и, возможно, вы хотите добавить:

_.bindAll(this, 'renderMap, 'renderPin');

к методу MapModalView initialize, чтобы эти два всегда имели право this при вызове.


И теперь для основной проблемы теперь, когда у нас есть в основном функциональный код.

Магистральные представления имеют el:

Все представлениявсегда иметь элемент DOM (свойство el), независимо от того, были ли они уже вставлены на страницу или нет.

и имеют $el:

Кэшированный объект jQuery (или Zepto) для элемента представления.

Операторы метода delegateEvents для this.$el.Вы не указываете el (или id, tagName, ...) как часть определения вашего представления, поэтому Backbone инициализирует ваш el пустым <div>, а затем инициализирует this.$el = $(this.el).Ваш конструктор изменится this.el:

this.el = $('.modal_box');

, но вы ничего не сделаете с this.$el, поэтому он по-прежнему ссылается на пустой <div>.Помните, что delegateEvents использует this.$el, и это не указывает ни на что полезное, поэтому ваши события не привязываются ни к чему в DOM.

Если вы настаиваете на установке this.el внутри вашего initialize,тогда вам также нужно будет установить this.$el:

initialize: function() {
    this.el  = '.modal_box';
    this.$el = $(this.el);
    //...

Демо: http://jsfiddle.net/ambiguous/D996h/

Или вы можете использовать setElement() для установки el и $el для вас.

Обычный подход - установить el как часть определения представления:

MapModalView = Backbone.View.extend({
    el: '.modal_box',
    //...

Демонстрация: http://jsfiddle.net/ambiguous/NasSN/

Или вы можете передать el представлению при его создании:

m = new MapModalView({el: '.modal_box'});
m.render();

Демонстрация: http://jsfiddle.net/ambiguous/9rsdC/

1 голос
/ 22 февраля 2012

Попробуйте это:

render: function() {
    $(this.el).show().append(this.template({
        model: this.model
    }));
    this.renderMap();
    this.renderPin();
    this.delegateEvents();
},
...