Обработчик событий магистрали не работает

#javascript #jquery #backbone.js

#javascript #jquery #backbone.js

Вопрос:

У меня есть два представления — представление макета, которое является верхним уровнем, и представление новой формы, которое действует как дочерний элемент макета и отображается в нем. У меня есть один обработчик событий в представлении формы, который должен создавать новый экземпляр моей модели в соответствии с данными из входных данных.

Вот вид макета:

 var LayoutView = Backbone.View.extend({
    el: "#layout",
    render: function (view) {
        this.child = view;
        if (this.child) {
            this.child.remove();
        }
        this.$el.html(this.child.render().el);
        return this;
    }
});
  

и вот мой вид формы:

 var ResumeForm = Backbone.View.extend({
    events: {
        'click #create': 'createResume'
    },
    initialize: function () {
        this.template = _.template($('#new-resume').html());
    },
    render: function () {
        this.$el.html(this.template());
        return this;
    },
    createResume: function () {
        // getting values from template inputs and saving them to model
        var resume = new Resume({
            profession: $('#profession').val(),
            firstName: $('#firstname').val(),
            lastName: $('#lastname').val()
        });
        // saving a new model to collection instance
        resumes.add(resume);
        resume.save(null, {
            success: function (res) {
                console.log("POST resume id "   res.toJSON().id);
            },
            error: function () {
                console.log("Failed to POST");
            }
        });
    }
});
  

Мое представление формы отлично отображается в моем представлении макета, но когда я ввожу значения и нажимаю #create кнопку, ничего не происходит — ни сохраняется модель, ни регистрируется ошибка ошибки из моего createResume метода. Я подозреваю, что при рендеринге представления формы в представлении макета строка this.$el.html(this.child.render().el); просто уничтожает всех прослушивателей событий, потому что, если я добавлю этих прослушивателей в представление макета, это сработает.

Есть ли какие-либо способы преодолеть эту проблему?

Ответ №1:

remove Функция просмотра Backbone отменяет отмену событий, связанных с el .

Из аннотированного источника:

 remove: function() {
    this._removeElement();
    this.stopListening();
    return this;
},

_removeElement: function() {
    this.$el.remove();
},
  

Это связано с .remove() функцией jQuery (выделение мое):

Аналогично .empty() , .remove() метод извлекает элементы из DOM. Используйте .remove() , когда вы хотите удалить сам элемент, а также все, что внутри него. В дополнение к самим элементам удаляются все связанные события и данные jQuery, связанные с элементами. Чтобы удалить элементы без удаления данных и событий, используйте .detach() вместо.

Если вы вызываете remove перед повторным использованием представления, вам нужно вручную вызвать this.delegateEvents() , чтобы повторно связать события из events хэша и повторно подключить любое событие, которое прослушивало представление this.listenTo(...) .

Но лучший способ повторно использовать представления, не remove вызывая вызовы which stopListening , вы можете использовать setElement which отменяет события и изменить элемент view на переданный элемент, а затем повторно делегировать события.

 setElement: function(element) {
    this.undelegateEvents();
    this._setElement(element);
    this.delegateEvents();
    return this;
},
  

Ваш LayoutView стал бы чем-то вроде этого:

 var LayoutView = Backbone.View.extend({
    el: "#layout",
    render: function(view) {
        // if the view is different, make sure to undelegate the old view.
        if (this.child amp;amp; this.child !== view) this.child.undelegateEvents();
        this.child = view;
        this.child.setElement(this.$el).render();
        return this;
    }
});
  

Комментарии:

1. Большое тебе спасибо, Эмиль! Это сработало отлично. Я думаю, мне следует больше читать документы. Теперь есть еще одна проблема — когда я нажимаю на #create кнопку, она выдает мне следующую ошибку: backbone.js:1907 Uncaught Error: A "url" property or function must be specified но это не имеет отношения к этому вопросу

2. @AlexNikolaev94 эта ошибка связана с тем, что ваша Resume модель не имеет urlRoot свойства или находится внутри коллекции, у которой есть url свойство.

3. он точно существует внутри коллекции, которая имеет url свойство. должен ли я удалить его и вместо этого добавить urlRoot свойство в модель?

4. @AlexNikolaev94 Я должен был бы посмотреть, но вы можете задать другой вопрос, и я или кто-то другой может вам помочь.