[英]Collection in Backbone.js Not Firing Events
我試圖在觸發給定集合中的模型更改時實現操作,但每當我嘗試將偵聽器放在我的集合上的change
, add
或remove
事件時,都不會觸發任何事件。 當我將更改事件附加到模型的initialize
函數(僅用於測試)時, change
事件已成功觸發。 下面的視圖本身不會更改代碼,但我希望每當對集合進行更改時它都會重新呈現。 我的設置可能有問題,但我想得到你的建議。 以下是我的代碼:
contact.js(型號):
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone){
var ContactModel = Backbone.Model.extend({
urlRoot: '/contacts'
});
return ContactModel;
});
contacts.js(收藏):
define([
'jquery',
'underscore',
'backbone',
'models/contact'
], function($, _, Backbone, Contact){
var ContactCollection = Backbone.Collection.extend({
url: '/contacts',
model: Contact
});
return ContactCollection;
});
contactlist.js(查看):
define([
'jquery',
'underscore',
'backbone',
'text!templates/contactlist.html',
'collections/contacts'
], function($, _, Backbone, contactListTemplate, Contacts){
var ContactListView = Backbone.View.extend({
el: '.contact-list',
render: function(options) {
var that = this;
var contacts = new Contacts();
contacts.on("add", function() {
console.log('change');
});
contacts.fetch({
success: function(contacts) {
var results = contacts.models;
if (options.query || options.query === '') {
var results = [];
var query = options.query.toUpperCase();
for (var contact in contacts.models) {
if (contacts.models[contact].get('firstname').toUpperCase().indexOf(query) !== -1 ||
contacts.models[contact].get('lastname').toUpperCase().indexOf(query) !== -1 ||
contacts.models[contact].get('email').toUpperCase().indexOf(query) !== -1 ||
contacts.models[contact].get('phonenumber').toString().toUpperCase().indexOf(query) !== -1)
{
results.push(contacts.models[contact]);
}
}
options.idclicked = null;
}
if (!options.idclicked && results[0]) {
options.idclicked = results[0].get('id');
Backbone.history.navigate('/contacts/' + results[0].get('id'), {trigger: true});
}
var template = _.template(contactListTemplate, {contacts: results, idclicked: options.idclicked});
that.$el.html(template);
$(document).ready(function() {
$('.contact-list').scrollTop(options.scrolled);
});
}
});
},
events: {
'click .contact': 'clickContact'
},
clickContact: function (ev) {
$('.contact-clicked').removeClass('contact-clicked').addClass('contact');
$(ev.currentTarget).addClass('contact-clicked').removeClass('contact');
window.location.replace($(ev.currentTarget).children('a').attr('href'));
}
});
return ContactListView;
});
自從Backbone 1.0( 更改日志 )以來,這個問題的答案不再是100%准確的。
在Backbone 1.0+中,如果要.fetch()
reset
事件,則必須將{ reset: true }
傳遞給.fetch()
方法。 見下文。
在集合上調用fetch
現在將觸發3個不同的事件:
collection.fetch(); //triggers the following events
request
:在發出ajax請求之前觸發 add
:(多次)當數據中的每個項目添加到集合中時,將多次觸發此事件。 sync
:在集合上的數據與數據提供程序同步后觸發(數據已添加到集合,ajax請求已完成) 要恢復到舊式的骨干事件,您需要調用
collection.fetch({ reset: true }); //triggers the following events
request
:在發出ajax請求之前觸發 reset
:將所有數據放入集合時觸發。 sync
:在集合上的數據與數據提供程序同步后觸發(數據已添加到集合,ajax請求已完成) 快速查看集合觸發的事件的最佳方法是綁定到all
事件並記錄參數:
collection.on('all', function() {
console.log(arguments);
});
運行fetch()
,集合將觸發它的reset
事件,而不是add
。
contacts.on("reset", function() {
console.log('reset');
});
在success
回調之前,一旦獲取完成,它就會運行。
當模型本身更改了屬性時, change
將運行,您在發布的代碼中不會執行任何操作。
通常我也不會直接訪問.models
。 我這樣做:
var results = contacts.toArray();
if (options.query || options.query === ''){
results = contacts.filter(function(contact){
return _.any(['firstname', 'lastname', 'email', 'phonenumber'], function(attr){
return contact.get(attr).toString().toUpperCase().indexOf(query) !== -1;
});
});
// ...
就像現在一樣,您在渲染時創建集合。 這不是一個好主意,因為理想情況下,您希望能夠再次渲染而無需再次獲取所有數據。
我將集合創建邏輯移動到視圖的initialize
函數中,如下所示:
initialize: function(options){
this.collection = new Contacts();
this.collection.on('reset add remove', this.render, this);
}
這樣,隨着集合的更改,渲染會自動觸發。 你的options
很復雜,所以我會嘗試改變你傳遞這些參數的方式。也許添加一個'setOptions'函數來保存渲染時使用的選項。 理想情況下, render
將重新呈現頁面與調用之前的相同,它通常不具有參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.