2016-10-31 1 views
0

Я настроил простую модель и представление с помощью базового шаблона с использованием шаблона подчеркивания. Точная конфигурация используется для двух отдельных API.визуализация не получает вызов для одного api и для другого

API 1 работает должным образом.

Чтобы воспроизвести проблему, закомментируйте URL для API 1 и раскомментируйте URL для API 2.

Как вы можете видеть, что я нормализовались данные ответа для обоих APIs, точно такая же структура данных возвращен для обоих 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

У вас есть условие гонки, где вы запрашиваете до создания представления.

Итак, если фишка завершается до того, как документ готов, событие изменения запускается до того, как представление начнет прослушивать модель.

Самое простое решение

$(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

Смежные вопросы