2

以下に、モジュールの1つのコードを示します。これは一種のスパゲッティっぽいコードですが、私が達成したいのは、モデルとコレクションを用意し、コレクションのデータをビューに接続するビューをレンダリングすることです(アンダースコアテンプレートを使用)。私は惨めに失敗しています。私が得ている問題は、testfeed.render()への最後の呼び出しを実行しようとすると、renderは関数ではないが、明確に定義されていることを示していることです。そのデータをフェッチして、APIからコレクションに追加できるようです。私はここで何が間違っているのですか?

 // Create a new module.
  var Tagfeed = app.module();

  // Default model.
  Tagfeed.Model = Backbone.Model.extend({
    defaults : {
        name : '',
        image : ''
    },
    initialize : function(){
        console.log('tagfeed model is initialized');
        this.on("change", function(){
            console.log("An attribute has been changed");
        });
    }
  });

  var feedCollection = Backbone.Collection.extend({
    model: Tagfeed.Model,
    initialize : function () {
        console.log('feedcollection is initialized');
    },
    fetch: function () {
        var thisCollection = this;
        Api_get('/api/test', function(data){

            $.each(data.data, function(){
                thisCollection.add(this);
            });
            return thisCollection;
        })
    }
  });

  var test = new Tagfeed.Model({name:'test'});

  var newFeedCollection = new feedCollection();

  newFeedCollection.fetch();

  console.log(newFeedCollection.at(0));

  var testfeed = Backbone.View.extend({
    el: $('#main'),
    collection : newFeedCollection,
    render: function( event ){
        var compiled_template = _.template( $("#tag-template").html() );
        this.$el.html( compiled_template(this.model.toJSON()) );
        return this; //recommended as this enables calls to be chained.
    }
  });

  testfeed.render();

編集* @muから更新されたコードは短い提案です

  // Create a new module.
  var Tagfeed = app.module();

  // Default model.
  var tagModel = Backbone.Model.extend({
    defaults : {
        name : '',
        image : '',
        pins : 0,
        repins : 0,
        impressions : 0
    },
    initialize : function(){
        console.log('tagfeed model is initialized');
        this.on("change", function(){
            console.log("An attribute has been changed");
        });
    }
  });

  var feedCollection = Backbone.Collection.extend({
    model: tagModel,
    initialize : function () {
        console.log('feedcollection is initialized');
    },
    fetch: function () {
        var thisCollection = this;

        Api_get('/reporting/adlift/pin_details', function(data){

            thisCollection.add(data.data);

            return data.data;
        })
    }
  });

  var test = new tagModel({name:'test'});

  var newFeedCollection = new feedCollection();

  newFeedCollection.fetch();

  console.log(newFeedCollection.at(0));

  var TestFeed = Backbone.View.extend({
    el: $('#main'),
    render: function( event ){
        console.log('here');
        var compiled_template = _.template( $("#tag-template").html(), this.collection.toJSON());
        this.el.html( compiled_template );
        return this; //recommended as this enables calls to be chained.
    },
    initialize: function() {
        console.log('initialize view');
        this.collection.on('reset', this.render, this);
    }
  });

  //Tagfeed.testfeed.prototype.render();

  var testfeed = new TestFeed({ collection: newFeedCollection });

  testfeed.render();

そして今、testfeed.render()を実行すると、エラーは表示されず、render関数にそのconsole.logも表示されません。考え?

4

2 に答える 2

8

あなたの問題はここにあります:

var testfeed = Backbone.View.extend({ /*...*/ });
testfeed.render();

これにより、ビューが「クラス」になります。レンダリングする前にtestfeed、で新しいインスタンスを作成する必要があります。new

var TestFeed = Backbone.View.extend({ /*...*/ });
var testfeed = new TestFeed();
testfeed.render();

「クラス」内でもこれを行っています。

collection : newFeedCollection

これはnewFeedCollection、そのビューの各インスタンスに関連付けられ、驚くべき動作を引き起こす可能性があります。コレクションをビューに取り込む通常の方法は、コレクションをコンストラクターに渡すことです。

var TestFeed = Backbone.View.extend({ /* As usual but not collection in here... */ });
var testfeed = new TestFeed({ collection: newFeedCollection });
testfeed.render();

ビューコンストラクターは、ビューを構築するthis.collectionときに渡すコレクションにビューを自動的に設定します。

考慮すべきもう1つのことは、これです。

newFeedCollection.fetch();

通常はAJAX呼び出しであるため、コレクションをレンダリングしようとすると、コレクションに何も含まれない可能性があります。私はこれに対処するために2つのことをします:

  1. ビューrenderは、空のコレクションを処理できる必要があります。これは主に、コレクションが空のときに賢明であるようにテンプレートが十分に賢いことに依存します。
  2. renderビューのコレクションの"reset"イベントにバインドしますinitialize

    initialize: function() {
        this.collection.on('reset', this.render, this);
    }
    

もう1つの問題は、ビューrenderがレンダリングしようとしていることthis.modelです。

this.$el.html( compiled_template(this.model.toJSON()) );

ビューがコレクションに基づいている場合。これを次のように変更します。

this.$el.html(compiled_template({ tags: this.collection.toJSON() }));

tagsテンプレートがコレクションデータを見るときに参照する名前を持つように、そこにが必要になります。

また、これを置き換えることができるはずです:

$.each(data.data, function(){
    thisCollection.add(this);
});

これだけで:

thisCollection.add(data.data);

それらを1つずつ追加する必要Collection#addはなく、モデルの配列に完全に満足しています。

そして、これが(うまくいけば)すべてが整理されたデモです:

http://jsfiddle.net/ambiguous/WXddy/

私は内部を偽造しfetchなければなりませんでしたが、他のすべてはそこにあるはずです。

于 2012-09-13T21:04:16.717 に答える
1

testfeedインスタンスではありません-コンストラクター関数です。

var instance = new testfeed(); 
instance.render();

おそらく機能します(elビュー定義中に定義すると、プロトタイププロパティ、IIRCになります)。

于 2012-09-13T20:59:51.573 に答える