2016-10-31 2 views
0

私はアンダースコアテンプレートを使用して単純なバックボーンモデルとビューを設定しました。 2つの別々のAPIで全く同じ設定が使用されます。レンダリングが1つのAPIに対して呼び出されず、別のものになります

API 1は期待どおりに動作します。

は、問題を再現API 1のURLをコメントアウトし、API 2.

あなたは、私は両方のAPIの応答データを正規化している見ることができるようにするために、URLのコメントを解除するには、まったく同じデータ構造があります両方の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バックボーンのベストプラクティスを自分のコードに追加しました。 –

+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

関連する問題