#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 Я должен был бы посмотреть, но вы можете задать другой вопрос, и я или кто-то другой может вам помочь.