2012-08-03 62 views
0

我正在嘗試創建我的第一個主幹應用程序,並且遇到了一些困難,難以理解我的意圖是如何使用視圖。引用一個集合的多個主幹視圖

我想要做的是有一個搜索輸入,每次提交它從服務器提取一個集合。我希望有一個視圖控制搜索輸入區域,並監聽發生在那裏的事件(在我的示例中點擊一個按鈕)以及另一個視圖,其中包含用於顯示搜索結果的子視圖。每次新的搜索都只是將搜索結果添加到搜索區域。

個人的結果將有其他方法(如查找他們在哪裏輸入等日期或時間)。

我有這樣定義的模型和集合:

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() 
    } 
}); 

在我的意見我已表示搜索輸入一個觀點是:

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');但沒有Ajax調用MA從ResultSetView集合的初始化方法到服務器。

我在設計這個權利還是有更好的方法來做到這一點。我認爲,因爲這兩個視圖綁定到不同的DOM元素,我不應該從另一個視圖中實例化一個視圖。任何建議表示讚賞,如果我需要說明這個更清楚,請讓我知道,我會盡我所能來重述這個問題。

+1

你是否看到任何JS錯誤被拋出? 此外,ajax調用將在您的'SearchResults''Collection'的初始化過程中進行,因爲這是您告訴它執行抓取的位置。 – bvulaj 2012-08-03 15:28:58

+0

是的,它會登錄到控制檯,但不會發生ajax請求。也沒有js錯誤。 – justinfay 2012-08-03 15:36:30

+0

請注意,在實際的實現中,'ResultView'實例將被創建,但它們的'render'結果將不會被添加到'SearchView。$ el'中。 – fguillen 2012-08-03 15:36:39

回答

2

一些問題(可能不是唯一的):

  • 搜索查看未綁定到集合復位事件;正如書面文字,它會立即嘗試渲染,而集合仍然是空的。
  • 搜索查看實例化單一視圖ResultView當推測它應該實例化複合視圖ResultSetView
  • 您正將一個參數傳遞給SearchResults集合的構造函數,但這不是正確的使用方法。關於這一點,請參閱documentation
+1

SearchView可能不需要像ResultSetView一樣監聽重置事件,但可以很好地調用其他註釋。 – JayC 2012-08-03 15:42:51

0

您還沒有告訴您的ResultSetView收聽收藏上的任何事件。 「獲取」是異步的。成功完成後,它將發送一個「重置」事件。您的視圖需要監聽該事件,然後執行該事件所需的任何操作(如渲染)。

0

在你的例子代碼修復所有錯別字後,我有一個working jsFiddle

單擊按鈕後,您會看到一個AJAX調用完成。當然,迴應是一個錯誤,但這不是重點。

所以我的結論是,你的問題是在你的代碼的另一部分。

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 
     }); 
    } 
}); 

請注意,我只創建了一次收藏。這就是你所需要的,因爲你使用相同的集合類來執行搜索。後續搜索只需要更改網址。這是更好的內存管理,比爲每個搜索實例化一個新的集合要乾淨一點。

我沒有在顯示視圖上進一步工作。但是,您可能會考慮堅持傳遞哈希到Backbone對象的約定。例如,在您的原始代碼中,您傳遞了'resultSet'作爲正式參數。但是,約定是將集合傳遞給以下形式的視圖:new View({collection:resultSet});我意識到這有點挑剔,但遵循約定提高了代碼的可讀性。此外,你確保你以Backbone對象期望的方式傳遞事物。