2016-10-31 28 views
0

我已經使用下劃線模板配置了一個簡單的骨幹模型和視圖。完全相同的配置用於兩個獨立的API。渲染沒有被調用一個API並且是另一個

API 1按預期工作。

要重現該問題,註釋掉的URL API 1,取消對URL的API 2.

正如你可以看到我已經規範了兩種API響應數據,完全相同的數據結構爲兩個apis返回。但是,不調用API 2的渲染方法。更奇怪的是,在極少數情況下渲染確實被API 2調用。

我在這裏丟失了什麼?

// Model 
 
var Quote = Backbone.Model.extend({ 
 
    // API 1 
 
    //urlRoot: 'http://quotes.stormconsultancy.co.uk/quotes/1.json', 
 
    
 
    // API 2 
 
    urlRoot: 'http://quotes.rest/qod.json', 
 

 
    parse: function (data){ 
 
    try{ 
 
     data = data['contents'].quotes[0]; 
 
    } 
 
    catch(e){ 
 
    } 
 

 
    var rd = {author:data.author, quote:data.quote} 
 
    console.log("parsed", typeof rd, rd); 
 
    return rd; 
 
    }, 
 
    
 
    // UPDATE as suggested by cory 
 
    initialize: function() { 
 
    this.on('all', function(eventName) { 
 
     console.log('QuoteModel: ' + eventName); 
 
    }); 
 
    } 
 
}); 
 

 
// View 
 
var QuoteView = Backbone.View.extend({ 
 
    initialize: function() { 
 
    this.template = _.template($('#quote-template').html()); 
 
    this.listenTo(this.model, 'change', this.render); 
 
    }, 
 

 
    render: function(){ 
 
    console.log("render", this.model.attributes) 
 
    this.$el.html(this.template(this.model.attributes)); 
 
    } 
 
}); 
 

 
var quoteM = new Quote(); 
 
quoteM.fetch(); 
 

 
$(document).ready(function() { 
 
\t var quoteV = new QuoteView({ 
 
\t \t el: $('#quote'), 
 
\t \t model: quoteM 
 
\t }); 
 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script> 
 

 
<script type="text/html" id="quote-template"> 
 
\t \t <p>The author is : <%= author %></p> 
 
\t \t <p>The content is : <%= quote %></p> 
 
</script> 
 

 
<div id="quote"></div>

回答

1

你有競爭條件,在那裏你創建視圖之前提取。

因此,如果抓取在文檔準備好之前完成,則在視圖開始偵聽模型之前觸發change事件。

最簡單的辦法

$(document).ready(function() { 
    var quoteM = new Quote(); 
    var quoteV = new QuoteView({ 
     el: $('#quote'), 
     model: quoteM 
    }); 
    // fetch after 
    quoteM.fetch(); 
}); 

最好的解決辦法

var API_DOMAIN = "http://quotes.rest/"; 
 
// Reusable model 
 
var Quote = Backbone.Model.extend({}); 
 

 
// reusable quotes collection 
 
var QuoteCollection = Backbone.Collection.extend({ 
 
    model: Quote, 
 
    // simple generic parse 
 
    parse: function(response) { 
 
    return response.contents.quotes; 
 
    }, 
 
}); 
 

 
// View 
 
var QuoteView = Backbone.View.extend({ 
 
    // GOOD: gets called once 
 
    template: _.template($('#quote-template').html()), 
 
    
 
    initialize: function() { 
 
    // BAD: gets called for every view 
 
    // this.template = _.template($('#quote-template').html()); 
 
    
 
    this.listenTo(this.model, 'change', this.render); 
 
    }, 
 

 
    render: function() { 
 
    console.log("render", this.model.attributes) 
 
    this.$el.html(this.template(this.model.toJSON())); 
 
    // Backbone standard for chaining 
 
    return this; 
 
    } 
 
}); 
 

 

 
$(function() { 
 
    var quoteV, 
 
    collection = new QuoteCollection(); 
 
    collection.fetch({ 
 
    url: API_DOMAIN + 'qod.json', 
 
    success: function(collection, response, options) { 
 
     // only create the view when you need it 
 
     quoteV = new QuoteView({ 
 
     el: $('#quote'), 
 
     model: collection.first() 
 
     }); 
 
     
 
     // manually render to be 100% in control. The event now only 
 
     // serves if the model really changes. 
 
     quoteV.render(); 
 
    } 
 
    }); 
 

 
});
<div id="quote"></div> 
 

 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script> 
 

 
<script type="text/html" id="quote-template"> 
 
    <p>The author is : 
 
    <%= author %> 
 
    </p> 
 
    <p>The content is : 
 
    <%= quote %> 
 
    </p> 
 
</script>

+0

謝謝!不能相信我錯過了這一點。 – arctelix

+0

@arctelix我已經將Backbone的最佳實踐添加到了我的答案中。 –

+0

感謝您的更新答案! – arctelix

1

添加一些日誌記錄在你的報價模型的事件,你應該能夠迅速追查問題。

var Quote = Backbone.Model.extend({ 
    initialize: function() { 
     this.on('all', function(eventName) { 
      console.debug('QuoteModel: ' + eventName); 
     }); 
    } 
}); 
+0

我已經添加了額外的日誌記錄,唯一不同的是,使被調用API 1,而不是API 2 ... – arctelix

相關問題