簡體   English   中英

Backbone.js中的集合不會觸發事件

[英]Collection in Backbone.js Not Firing Events

我試圖在觸發給定集合中的模型更改時實現操作,但每當我嘗試將偵聽器放在我的集合上的changeaddremove事件時,都不會觸發任何事件。 當我將更改事件附加到模型的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
  1. request :在發出ajax請求之前觸發
  2. add :(多次)當數據中的每個項目添加到集合中時,將多次觸發此事件。
  3. sync :在集合上的數據與數據提供程序同步后觸發(數據已添加到集合,ajax請求已完成)

要恢復到舊式的骨干事件,您需要調用

collection.fetch({ reset: true }); //triggers the following events
  1. request :在發出ajax請求之前觸發
  2. reset :將所有數據放入集合時觸發。
  3. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM