我使用下划线模板配置了一个简单的主干模型和视图。完全相同的配置用于两个单独的API。
API 1按预期工作。
要重现此问题,请注释掉API 1的网址并取消注释API 2的网址。
正如您所看到的,我已经对两个api的响应数据进行了规范化,两个api都返回了完全相同的数据结构。但是,不会调用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() {
var quoteV = new QuoteView({
el: $('#quote'),
model: quoteM
});
});
<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>
<div id="quote"></div>
答案 0 :(得分:1)
为Quote模型上的事件添加一些日志记录,您应该能够快速找到问题。
var Quote = Backbone.Model.extend({
initialize: function() {
this.on('all', function(eventName) {
console.debug('QuoteModel: ' + eventName);
});
}
});
答案 1 :(得分:1)
您有一个竞争条件,您可以在创建视图之前获取。
因此,如果在文档准备就绪之前完成提取,则在视图开始侦听模型之前触发更改事件。
$(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();
}
});
});
&#13;
<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>
&#13;