0

初めてのバックボーン アプリを作成しようとしていますが、ビューの使用方法を理解するのに苦労しています。

私がやろうとしているのは、送信されるたびにサーバーからコレクションを取得する検索入力を用意することです。1 つのビューで検索入力領域を制御し、そこで発生するイベント (この例ではボタンのクリック) をリッスンし、別のビューで検索結果を表示するサブビューを作成したいと考えています。新しい検索ごとに、結果を検索領域の前に追加するだけです。

個々の結果には、他の方法があります (入力された日付や時刻の検索など)。

次のように定義されたモデルとコレクションがあります。

SearchResult = Backbone.model.extend({
    defaults: {
        title: null,
        text: null
    }
});

SearchResults = Backbone.Collection.extend({
    model: SearchResult,
    initialize: function(query){
        this.query = query;
        this.fetch();
    },
    url: function() {
        return '/search/' + this.query()
    }
});

私のビューでは、検索入力を表すビューが 1 つあります。

var SearchView = Backbone.View.extend({
    el: $('#search'),
    events: {
        'click button': 'doSearch' 
    },
    doSearch: function() {
        console.log('starting new search');
        var resultSet = new SearchResults($('input[type=text]', this.el).val());
        var resultSetView = new ResultView(resultSet); 
    }
});

var searchView = new SearchView();

var ResultSetView = Backbone.View.extend({
    el: $('#search'),
    initialize: function(resultSet) {
        this.collection = resultSet;
        this.render();
    },
    render: function() {
        _(this.collection.models).each(function(result) {
            var resultView = new ResultView({model:result});
        }, this);
    }
});

var ResultView = Backbone.view.extend({
     tagName: 'div',
     model: SearchResult,
     initialize: function() {
         this.render();
     },
     render: function(){ 
         $(this.el).append(this.model.get(title) + '<br>' + this.model.get('text'));
     }
});

私のhtmlはおおよそ次のようになります。

<body>
<div id="search">
    <input type="text">
    <button>submit</button>
</div>
<div id="results">

</div>

</body>

私のコードではconsole.log('starting new search');、ResultSetView コレクションの初期化メソッドからサーバーへの ajax 呼び出しは行われません。

私はこれを正しく設計していますか、それともこれを行うためのより良い方法がありますか? 2 つのビューは異なる dom 要素にバインドされるため、あるビューを別のビューからインスタンス化するべきではないと思います。アドバイスをいただければ幸いです。これをより明確に述べる必要がある場合はお知らせください。質問を言い換えるために最善を尽くします。

4

4 に答える 4

2

いくつかの問題 (おそらく唯一の問題ではありません):

  • SearchViewはコレクションのリセットイベントにバインドされていません。書かれているように、コレクションがまだ空である間に、すぐにレンダリングを試みます。
  • SearchViewは、おそらく複合ビューResultSetViewをインスタンス化する必要があるときに、単一ビューResultViewをインスタンス化します。
  • SearchResultsコレクションのコンストラクターにパラメーターを渡していますが、それは正しい使用方法ではありません。この点については、ドキュメントを参照してください。
于 2012-08-03T15:39:27.250 に答える
0

いくつかの構文の問題の中で、私があなたのコードで見た最も可能性の高い問題は競合状態です。ビューでは、フェッチによってデータが既に取得されており、ビューのレンダリングメソッドが実行されていると想定しています。非常に高速な操作の場合、それは有効かもしれませんが、データが存在することを本当に知る方法はありません。これに対処する方法は、他の人が提案しているとおりです。コレクションのリセットイベントをリッスンする必要があります。ただし、フェッチが発生する「タイミング」も制御する必要があるため、必要な場合にのみフェッチを実行することをお勧めします。つまり、検索ビュー内でフェッチを呼び出します。コレクションと検索ビューを少し再構築しました。

var SearchResults = Backbone.Collection.extend({
    model: SearchResult,
    execSearch : function(query) {
        this.url = '/search/' + query;
        this.fetch();
    }
});

var SearchView = Backbone.View.extend({
    el: $('#search'),
    initialize : function() {
        this.collection = new SearchResults();
        //listen for the reset
        this.collection.on('reset',this.displayResults,this);
    },
    events: {
        'click button': 'doSearch' 
    },
    /**
    * Do search executes the search
    */
    doSearch: function() {
        console.log('starting new search');
        //Set the search params and do the fetch.
        //Since we're listening to the 'reset' event, 
        //displayResults will execute. 
        this.collection.execSearch($('input[type=text]', this.el).val());
    },
    /**
    * displayResults sets up the views. Since we know that the
    * data has been fetched, just pass the collection, and parse it
    */
    displayResults : function() {
        new ResultSetView({
            collection : this.collection
        });
    }
});

コレクションを作成したのは1回だけであることに注意してください。同じコレクションクラスを使用して検索を実行しているので、必要なのはこれだけです。その後の検索では、URLを変更するだけで済みます。これは、検索ごとに新しいコレクションをインスタンス化するよりも優れたメモリ管理と少しクリーンです。

私はあなたのディスプレイビューについてこれ以上作業しませんでした。ただし、バックボーンオブジェクトにハッシュを渡すという規則に従うことを検討することもできます。たとえば、元のコードでは、正式なパラメータとして「resultSet」を渡しました。ただし、慣例では、コレクションを次の形式のビューに渡します。new View({collection:resultSet}); これは少し厄介なことだと思いますが、規則に従うとコードの可読性が向上します。また、Backboneオブジェクトが期待する方法で物事を渡していることを確認します。

于 2012-08-03T16:45:30.100 に答える
0

ResultSetViewコレクションのイベントをリッスンするように指示していません。「フェッチ」は非同期です。正常に完了すると、「リセット」イベントが送信されます。ビューはそのイベントをリッスンし、そのイベントで必要なこと (レンダリングなど) を実行する必要があります。

于 2012-08-03T15:38:43.927 に答える
0

サンプルコードのすべてのタイプミスを修正した後、動作する jsFiddleができました。

ボタンをクリックすると、AJAX 呼び出しが行われたように見えます。もちろん、応答はエラーですが、これは問題ではありません。

したがって、私の結論は、問題はコードの別の部分にあるということです。

于 2012-08-03T15:50:53.600 に答える